1
As promised, more Arm patches. The big thing in here is the
1
This pullreq is (1) my GICv4 patches (2) most of the first third of RTH's
2
MPS2-AN521 board model.
2
cleanup patchset (3) one patch fixing an smmuv3 bug...
3
3
4
thanks
4
thanks
5
-- PMM
5
-- PMM
6
6
7
The following changes since commit cfe6c547690b06fbce54a6d0f7b05dd7f18e36ea:
7
The following changes since commit a74782936dc6e979ce371dabda4b1c05624ea87f:
8
8
9
Merge remote-tracking branch 'remotes/xanclic/tags/pull-block-2019-01-31' into staging (2019-01-31 19:26:09 +0000)
9
Merge tag 'pull-migration-20220421a' of https://gitlab.com/dagrh/qemu into staging (2022-04-21 18:48:18 -0700)
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-20190201
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220422
14
14
15
for you to fetch changes up to 7743b70ffe7a8ce168adce2cf50ad156b1fefb8c:
15
for you to fetch changes up to 9792130613191c1e0c34109918c5e07b9f1429a5:
16
16
17
tests/microbit-test: Add tests for nRF51 NVMC (2019-02-01 15:32:17 +0000)
17
hw/arm/smmuv3: Pass the actual perm to returned IOMMUTLBEntry in smmuv3_translate() (2022-04-22 10:19:15 +0100)
18
18
19
----------------------------------------------------------------
19
----------------------------------------------------------------
20
target-arm queue:
20
target-arm queue:
21
* New machine mps2-an521 -- this is a model of the AN521 FPGA image for the MPS2 devboard
21
* Implement GICv4 emulation
22
* Fix various places where we failed to UNDEF invalid A64 instructions
22
* Some cleanup patches in target/arm
23
* Don't UNDEF a valid FCMLA on 32-bit inputs
23
* hw/arm/smmuv3: Pass the actual perm to returned IOMMUTLBEntry in smmuv3_translate()
24
* Fix some bugs in the newly-added PAuth implementation
25
* microbit: Implement NVMC non-volatile memory controller
26
24
27
----------------------------------------------------------------
25
----------------------------------------------------------------
28
Aaron Lindsay OS (2):
26
Peter Maydell (41):
29
target/arm: Send interrupts on PMU counter overflow
27
hw/intc/arm_gicv3_its: Add missing blank line
30
target/arm: Add a timer to predict PMU counter overflow
28
hw/intc/arm_gicv3: Sanity-check num-cpu property
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
31
68
32
Julia Suvorova (1):
69
Richard Henderson (19):
33
arm: Clarify the logic of set_pc()
70
target/arm: Update ISAR fields for ARMv8.8
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
34
89
35
Peter Maydell (33):
90
Xiang Chen (1):
36
armv7m: Don't assume the NVIC's CPU is CPU 0
91
hw/arm/smmuv3: Pass the actual perm to returned IOMMUTLBEntry in smmuv3_translate()
37
armv7m: Make cpu object a child of the armv7m container
38
armv7m: Pass through start-powered-off CPU property
39
hw/arm/iotkit: Rename IoTKit to ARMSSE
40
hw/arm/iotkit: Refactor into abstract base class and subclass
41
hw/arm/iotkit: Rename 'iotkit' local variables and functions
42
hw/arm/iotkit: Rename files to hw/arm/armsse.[ch]
43
hw/misc/iotkit-secctl: Support 4 internal MPCs
44
hw/arm/armsse: Make number of SRAM banks parameterised
45
hw/arm/armsse: Make SRAM bank size configurable
46
hw/arm/armsse: Support dual-CPU configuration
47
hw/arm/armsse: Give each CPU its own view of memory
48
hw/arm/armsse: Put each CPU in its own cluster object
49
iotkit-sysinfo: Make SYS_VERSION and SYS_CONFIG configurable
50
hw/arm/armsse: Add unimplemented-device stubs for MHUs
51
hw/arm/armsse: Add unimplemented-device stubs for PPUs
52
hw/arm/armsse: Add unimplemented-device stub for cache control registers
53
hw/arm/armsse: Add unimplemented-device stub for CPU local control registers
54
hw/misc/armsse-cpuid: Implement SSE-200 CPU_IDENTITY register block
55
hw/arm/armsse: Add CPU_IDENTITY block to SSE-200
56
hw/arm/armsse: Add SSE-200 model
57
hw/arm/mps2-tz: Add IRQ infrastructure to support SSE-200
58
hw/arm/mps2-tz: Add mps2-an521 model
59
target/arm/translate-a64: Don't underdecode system instructions
60
target/arm/translate-a64: Don't underdecode PRFM
61
target/arm/translate-a64: Don't underdecode SIMD ld/st multiple
62
target/arm/translate-a64: Don't underdecode SIMD ld/st single
63
target/arm/translate-a64: Don't underdecode add/sub extended register
64
target/arm/translate-a64: Don't underdecode FP insns
65
target/arm/translate-a64: Don't underdecode SDOT and UDOT
66
exec.c: Don't reallocate IOMMUNotifiers that are in use
67
target/arm/translate-a64: Fix FCMLA decoding error
68
target/arm/translate-a64: Fix mishandling of size in FCMLA decode
69
92
70
Remi Denis-Courmont (2):
93
docs/system/arm/virt.rst | 5 +-
71
target/arm: fix AArch64 virtual address space size
94
hw/intc/gicv3_internal.h | 231 ++++++++-
72
target/arm: fix decoding of B{,L}RA{A,B}
95
include/hw/arm/virt.h | 19 +-
73
96
include/hw/intc/arm_gicv3_common.h | 13 +
74
Richard Henderson (5):
97
include/hw/intc/arm_gicv3_its_common.h | 1 +
75
target/arm: Enable API, APK bits in SCR, HCR
98
target/arm/cpu.h | 59 ++-
76
target/arm: Always enable pac keys for user-only
99
target/arm/translate-a32.h | 13 +-
77
aarch64-linux-user: Update HWCAP bits from linux 5.0-rc1
100
target/arm/translate.h | 17 +-
78
aarch64-linux-user: Enable HWCAP bits for PAuth
101
hw/arm/smmuv3.c | 2 +-
79
linux-user: Initialize aarch64 pac keys
102
hw/arm/virt.c | 102 +++-
80
103
hw/intc/arm_gicv3_common.c | 54 +-
81
Steffen Görtz (3):
104
hw/intc/arm_gicv3_cpuif.c | 195 ++++++--
82
hw/nvram/nrf51_nvm: Add nRF51 non-volatile memories
105
hw/intc/arm_gicv3_dist.c | 7 +-
83
arm: Instantiate NRF51 special NVM's and NVMC
106
hw/intc/arm_gicv3_its.c | 876 +++++++++++++++++++++++++++------
84
tests/microbit-test: Add tests for nRF51 NVMC
107
hw/intc/arm_gicv3_its_kvm.c | 2 +
85
108
hw/intc/arm_gicv3_kvm.c | 5 +
86
kumar sourav (1):
109
hw/intc/arm_gicv3_redist.c | 480 +++++++++++++++---
87
hw/arm/nrf51_soc: set object owner in memory_region_init_ram
110
linux-user/arm/cpu_loop.c | 2 +-
88
111
target/arm/cpu.c | 16 +-
89
hw/arm/Makefile.objs | 2 +-
112
target/arm/helper-a64.c | 4 +-
90
hw/misc/Makefile.objs | 1 +
113
target/arm/helper.c | 19 +-
91
hw/nvram/Makefile.objs | 1 +
114
target/arm/hvf/hvf.c | 2 +-
92
include/hw/arm/{iotkit.h => armsse.h} | 113 ++-
115
target/arm/m_helper.c | 6 +-
93
include/hw/arm/armv7m.h | 1 +
116
target/arm/op_helper.c | 13 -
94
include/hw/arm/nrf51_soc.h | 2 +
117
target/arm/translate-a64.c | 50 +-
95
include/hw/misc/armsse-cpuid.h | 41 ++
118
target/arm/translate-m-nocp.c | 12 +-
96
include/hw/misc/iotkit-secctl.h | 6 +-
119
target/arm/translate-neon.c | 21 +-
97
include/hw/misc/iotkit-sysinfo.h | 6 +
120
target/arm/translate-sve.c | 9 +-
98
include/hw/nvram/nrf51_nvm.h | 64 ++
121
target/arm/translate-vfp.c | 76 +--
99
include/qom/cpu.h | 16 +-
122
target/arm/translate.c | 101 ++--
100
linux-user/aarch64/target_syscall.h | 2 +
123
hw/intc/trace-events | 18 +-
101
target/arm/cpu.h | 12 +-
124
31 files changed, 1890 insertions(+), 540 deletions(-)
102
exec.c | 10 +-
103
hw/arm/armsse.c | 1241 +++++++++++++++++++++++++++++++++
104
hw/arm/armv7m.c | 23 +-
105
hw/arm/boot.c | 4 -
106
hw/arm/iotkit.c | 759 --------------------
107
hw/arm/mps2-tz.c | 121 +++-
108
hw/arm/nrf51_soc.c | 44 +-
109
hw/intc/armv7m_nvic.c | 3 +-
110
hw/misc/armsse-cpuid.c | 134 ++++
111
hw/misc/iotkit-secctl.c | 5 +-
112
hw/misc/iotkit-sysinfo.c | 15 +-
113
hw/nvram/nrf51_nvm.c | 388 +++++++++++
114
linux-user/aarch64/cpu_loop.c | 31 +-
115
linux-user/elfload.c | 10 +
116
target/arm/arm-powerctl.c | 3 -
117
target/arm/cpu.c | 41 +-
118
target/arm/cpu64.c | 75 --
119
target/arm/helper.c | 139 +++-
120
target/arm/translate-a64.c | 59 +-
121
tests/microbit-test.c | 108 +++
122
MAINTAINERS | 6 +-
123
default-configs/arm-softmmu.mak | 3 +-
124
hw/misc/trace-events | 4 +
125
36 files changed, 2552 insertions(+), 941 deletions(-)
126
rename include/hw/arm/{iotkit.h => armsse.h} (53%)
127
create mode 100644 include/hw/misc/armsse-cpuid.h
128
create mode 100644 include/hw/nvram/nrf51_nvm.h
129
create mode 100644 hw/arm/armsse.c
130
delete mode 100644 hw/arm/iotkit.c
131
create mode 100644 hw/misc/armsse-cpuid.c
132
create mode 100644 hw/nvram/nrf51_nvm.c
133
diff view generated by jsdifflib
New 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.
1
4
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
1
Rather than just creating the CPUs with object_new, make them child
1
In the GICv3 code we implicitly rely on there being at least one CPU
2
objects of the armv7m container. This will allow the cluster code to
2
and thus at least one redistributor and CPU interface. Sanity-check
3
find the CPUs if an armv7m object is made a child of a cluster object.
3
that the property the board code sets is not zero.
4
object_new_with_props() will do the parenting for us.
5
4
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20190121185118.18550-3-peter.maydell@linaro.org
7
Message-id: 20220408141550.1271295-3-peter.maydell@linaro.org
10
---
8
---
11
hw/arm/armv7m.c | 7 ++++++-
9
hw/intc/arm_gicv3_common.c | 4 ++++
12
1 file changed, 6 insertions(+), 1 deletion(-)
10
1 file changed, 4 insertions(+)
13
11
14
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
12
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/armv7m.c
14
--- a/hw/intc/arm_gicv3_common.c
17
+++ b/hw/arm/armv7m.c
15
+++ b/hw/intc/arm_gicv3_common.c
18
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
16
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
19
17
s->num_irq, GIC_INTERNAL);
20
memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
18
return;
21
19
}
22
- s->cpu = ARM_CPU(object_new(s->cpu_type));
20
+ if (s->num_cpu == 0) {
23
+ s->cpu = ARM_CPU(object_new_with_props(s->cpu_type, OBJECT(s), "cpu",
21
+ error_setg(errp, "num-cpu must be at least 1");
24
+ &err, NULL));
25
+ if (err != NULL) {
26
+ error_propagate(errp, err);
27
+ return;
22
+ return;
28
+ }
23
+ }
29
24
30
object_property_set_link(OBJECT(s->cpu), OBJECT(&s->container), "memory",
25
/* ITLinesNumber is represented as (N / 32) - 1, so this is an
31
&error_abort);
26
* implementation imposed restriction, not an architectural one,
32
--
27
--
33
2.20.1
28
2.25.1
34
35
diff view generated by jsdifflib
1
In the "add/subtract (extended register)" encoding group, the "opt"
1
Boards using the GICv3 need to configure it with both the total
2
field in bits [23:22] must be zero. Correctly UNDEF the unallocated
2
number of CPUs and also the sizes of all the memory regions which
3
encodings where this field is not zero.
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.
4
13
5
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
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
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190125182626.9221-6-peter.maydell@linaro.org
24
Message-id: 20220408141550.1271295-4-peter.maydell@linaro.org
9
---
25
---
10
target/arm/translate-a64.c | 3 ++-
26
hw/intc/arm_gicv3_common.c | 4 ++--
11
1 file changed, 2 insertions(+), 1 deletion(-)
27
1 file changed, 2 insertions(+), 2 deletions(-)
12
28
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
29
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
14
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
31
--- a/hw/intc/arm_gicv3_common.c
16
+++ b/target/arm/translate-a64.c
32
+++ b/hw/intc/arm_gicv3_common.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
33
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
18
int imm3 = extract32(insn, 10, 3);
34
for (i = 0; i < s->nb_redist_regions; i++) {
19
int option = extract32(insn, 13, 3);
35
rdist_capacity += s->redist_region_count[i];
20
int rm = extract32(insn, 16, 5);
36
}
21
+ int opt = extract32(insn, 22, 2);
37
- if (rdist_capacity < s->num_cpu) {
22
bool setflags = extract32(insn, 29, 1);
38
+ if (rdist_capacity != s->num_cpu) {
23
bool sub_op = extract32(insn, 30, 1);
39
error_setg(errp, "Capacity of the redist regions(%d) "
24
bool sf = extract32(insn, 31, 1);
40
- "is less than number of vcpus(%d)",
25
@@ -XXX,XX +XXX,XX @@ static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
41
+ "does not match the number of vcpus(%d)",
26
TCGv_i64 tcg_rd;
42
rdist_capacity, s->num_cpu);
27
TCGv_i64 tcg_result;
28
29
- if (imm3 > 4) {
30
+ if (imm3 > 4 || opt != 0) {
31
unallocated_encoding(s);
32
return;
43
return;
33
}
44
}
34
--
45
--
35
2.20.1
46
2.25.1
36
37
diff view generated by jsdifflib
New patch
1
We use the common function gicv3_idreg() to supply the CoreSight ID
2
register values for the GICv3 for the copies of these ID registers in
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.)
1
9
10
Make gicv3_idreg() take an extra argument for the PIDR0 value.
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-5-peter.maydell@linaro.org
15
---
16
hw/intc/gicv3_internal.h | 15 +++++++++++++--
17
hw/intc/arm_gicv3_dist.c | 2 +-
18
hw/intc/arm_gicv3_its.c | 2 +-
19
hw/intc/arm_gicv3_redist.c | 2 +-
20
4 files changed, 16 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 @@ static inline uint32_t gicv3_iidr(void)
27
return 0x43b;
28
}
29
30
-static inline uint32_t gicv3_idreg(int regoffset)
31
+/* CoreSight PIDR0 values for ARM GICv3 implementations */
32
+#define GICV3_PIDR0_DIST 0x92
33
+#define GICV3_PIDR0_REDIST 0x93
34
+#define GICV3_PIDR0_ITS 0x94
35
+
36
+static inline uint32_t gicv3_idreg(int regoffset, uint8_t pidr0)
37
{
38
/* Return the value of the CoreSight ID register at the specified
39
* offset from the first ID register (as found in the distributor
40
@@ -XXX,XX +XXX,XX @@ static inline uint32_t gicv3_idreg(int regoffset)
41
static const uint8_t gicd_ids[] = {
42
0x44, 0x00, 0x00, 0x00, 0x92, 0xB4, 0x3B, 0x00, 0x0D, 0xF0, 0x05, 0xB1
43
};
44
- return gicd_ids[regoffset / 4];
45
+
46
+ regoffset /= 4;
47
+
48
+ if (regoffset == 4) {
49
+ return pidr0;
50
+ }
51
+ return gicd_ids[regoffset];
52
}
53
54
/**
55
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/intc/arm_gicv3_dist.c
58
+++ b/hw/intc/arm_gicv3_dist.c
59
@@ -XXX,XX +XXX,XX @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
60
}
61
case GICD_IDREGS ... GICD_IDREGS + 0x2f:
62
/* ID registers */
63
- *data = gicv3_idreg(offset - GICD_IDREGS);
64
+ *data = gicv3_idreg(offset - GICD_IDREGS, GICV3_PIDR0_DIST);
65
return true;
66
case GICD_SGIR:
67
/* WO registers, return unknown value */
68
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
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
--
95
2.25.1
diff view generated by jsdifflib
New 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.
1
9
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
New 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.
1
4
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
New 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.
1
6
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
New patch
1
Implement the GICv4 VMAPI and VMAPTI commands. These write
2
an interrupt translation table entry that maps (DeviceID,EventID)
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.
1
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
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20220408141550.1271295-9-peter.maydell@linaro.org
14
---
15
hw/intc/gicv3_internal.h | 9 ++++
16
hw/intc/arm_gicv3_its.c | 91 ++++++++++++++++++++++++++++++++++++++++
17
hw/intc/trace-events | 2 +
18
3 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 @@ FIELD(GITS_TYPER, CIL, 36, 1)
25
#define GITS_CMD_INVALL 0x0D
26
#define GITS_CMD_MOVALL 0x0E
27
#define GITS_CMD_DISCARD 0x0F
28
+#define GITS_CMD_VMAPTI 0x2A
29
+#define GITS_CMD_VMAPI 0x2B
30
31
/* MAPC command fields */
32
#define ICID_LENGTH 16
33
@@ -XXX,XX +XXX,XX @@ FIELD(MOVI_0, DEVICEID, 32, 32)
34
FIELD(MOVI_1, EVENTID, 0, 32)
35
FIELD(MOVI_2, ICID, 0, 16)
36
37
+/* VMAPI, VMAPTI command fields */
38
+FIELD(VMAPTI_0, DEVICEID, 32, 32)
39
+FIELD(VMAPTI_1, EVENTID, 0, 32)
40
+FIELD(VMAPTI_1, VPEID, 32, 16)
41
+FIELD(VMAPTI_2, VINTID, 0, 32) /* VMAPTI only */
42
+FIELD(VMAPTI_2, DOORBELL, 32, 32)
43
+
44
/*
45
* 12 bytes Interrupt translation Table Entry size
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
49
--- a/hw/intc/arm_gicv3_its.c
50
+++ b/hw/intc/arm_gicv3_its.c
51
@@ -XXX,XX +XXX,XX @@ static inline bool intid_in_lpi_range(uint32_t id)
52
id < (1 << (GICD_TYPER_IDBITS + 1));
53
}
54
55
+static inline bool valid_doorbell(uint32_t id)
56
+{
57
+ /* Doorbell fields may be an LPI, or 1023 to mean "no doorbell" */
58
+ return id == INTID_SPURIOUS || intid_in_lpi_range(id);
59
+}
60
+
61
static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
62
{
63
uint64_t result = 0;
64
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
65
return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE : CMD_STALL;
66
}
67
68
+static ItsCmdResult process_vmapti(GICv3ITSState *s, const uint64_t *cmdpkt,
69
+ bool ignore_vintid)
70
+{
71
+ uint32_t devid, eventid, vintid, doorbell, vpeid;
72
+ uint32_t num_eventids;
73
+ DTEntry dte;
74
+ ITEntry ite;
75
+
76
+ if (!its_feature_virtual(s)) {
77
+ return CMD_CONTINUE;
78
+ }
79
+
80
+ devid = FIELD_EX64(cmdpkt[0], VMAPTI_0, DEVICEID);
81
+ eventid = FIELD_EX64(cmdpkt[1], VMAPTI_1, EVENTID);
82
+ vpeid = FIELD_EX64(cmdpkt[1], VMAPTI_1, VPEID);
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;
160
default:
161
trace_gicv3_its_cmd_unknown(cmd);
162
break;
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
--
177
2.25.1
diff view generated by jsdifflib
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
Implement the GICv4 VMAPP command, which writes an entry to the vPE
2
table.
2
3
3
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
4
For GICv4.1 this command has extra fields in the command packet
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
5
and additional behaviour. We define the 4.1-only fields with the
5
Acked-by: Thomas Huth <thuth@redhat.com>
6
FIELD macro, but only implement the GICv4.0 version of the command.
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
7
Message-id: 20190201023357.22596-4-stefanha@redhat.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20220408141550.1271295-10-peter.maydell@linaro.org
9
---
11
---
10
tests/microbit-test.c | 108 ++++++++++++++++++++++++++++++++++++++++++
12
hw/intc/gicv3_internal.h | 12 ++++++
11
1 file changed, 108 insertions(+)
13
hw/intc/arm_gicv3_its.c | 88 ++++++++++++++++++++++++++++++++++++++++
14
hw/intc/trace-events | 2 +
15
3 files changed, 102 insertions(+)
12
16
13
diff --git a/tests/microbit-test.c b/tests/microbit-test.c
17
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/microbit-test.c
19
--- a/hw/intc/gicv3_internal.h
16
+++ b/tests/microbit-test.c
20
+++ b/hw/intc/gicv3_internal.h
17
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
18
#include "hw/arm/nrf51.h"
22
#define GITS_CMD_INVALL 0x0D
19
#include "hw/char/nrf51_uart.h"
23
#define GITS_CMD_MOVALL 0x0E
20
#include "hw/gpio/nrf51_gpio.h"
24
#define GITS_CMD_DISCARD 0x0F
21
+#include "hw/nvram/nrf51_nvm.h"
25
+#define GITS_CMD_VMAPP 0x29
22
#include "hw/timer/nrf51_timer.h"
26
#define GITS_CMD_VMAPTI 0x2A
23
#include "hw/i2c/microbit_i2c.h"
27
#define GITS_CMD_VMAPI 0x2B
24
28
25
@@ -XXX,XX +XXX,XX @@ static void test_microbit_i2c(void)
29
@@ -XXX,XX +XXX,XX @@ FIELD(VMAPTI_1, VPEID, 32, 16)
26
qtest_quit(qts);
30
FIELD(VMAPTI_2, VINTID, 0, 32) /* VMAPTI only */
31
FIELD(VMAPTI_2, DOORBELL, 32, 32)
32
33
+/* VMAPP command fields */
34
+FIELD(VMAPP_0, ALLOC, 8, 1) /* GICv4.1 only */
35
+FIELD(VMAPP_0, PTZ, 9, 1) /* GICv4.1 only */
36
+FIELD(VMAPP_0, VCONFADDR, 16, 36) /* GICv4.1 only */
37
+FIELD(VMAPP_1, DEFAULT_DOORBELL, 0, 32) /* GICv4.1 only */
38
+FIELD(VMAPP_1, VPEID, 32, 16)
39
+FIELD(VMAPP_2, RDBASE, 16, 36)
40
+FIELD(VMAPP_2, V, 63, 1)
41
+FIELD(VMAPP_3, VPTSIZE, 0, 8) /* For GICv4.0, bits [7:6] are RES0 */
42
+FIELD(VMAPP_3, VPTADDR, 16, 36)
43
+
44
/*
45
* 12 bytes Interrupt translation Table Entry size
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
49
--- a/hw/intc/arm_gicv3_its.c
50
+++ b/hw/intc/arm_gicv3_its.c
51
@@ -XXX,XX +XXX,XX @@ typedef struct ITEntry {
52
uint32_t vpeid;
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;
27
}
66
}
28
67
29
+#define FLASH_SIZE (256 * NRF51_PAGE_SIZE)
68
+/*
69
+ * Update the vPE Table entry at index @vpeid with the entry @vte.
70
+ * Returns true on success, false if there was a memory access error.
71
+ */
72
+static bool update_vte(GICv3ITSState *s, uint32_t vpeid, const VTEntry *vte)
73
+{
74
+ AddressSpace *as = &s->gicv3->dma_as;
75
+ uint64_t entry_addr;
76
+ uint64_t vteval = 0;
77
+ MemTxResult res = MEMTX_OK;
30
+
78
+
31
+static void fill_and_erase(QTestState *qts, hwaddr base, hwaddr size,
79
+ trace_gicv3_its_vte_write(vpeid, vte->valid, vte->vptsize, vte->vptaddr,
32
+ uint32_t address_reg)
80
+ vte->rdbase);
33
+{
34
+ hwaddr i;
35
+
81
+
36
+ /* Erase Page */
82
+ if (vte->valid) {
37
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
83
+ vteval = FIELD_DP64(vteval, VTE, VALID, 1);
38
+ qtest_writel(qts, NRF51_NVMC_BASE + address_reg, base);
84
+ vteval = FIELD_DP64(vteval, VTE, VPTSIZE, vte->vptsize);
39
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
85
+ vteval = FIELD_DP64(vteval, VTE, VPTADDR, vte->vptaddr);
40
+
86
+ vteval = FIELD_DP64(vteval, VTE, RDBASE, vte->rdbase);
41
+ /* Check memory */
42
+ for (i = 0; i < size / 4; i++) {
43
+ g_assert_cmpuint(qtest_readl(qts, base + i * 4), ==, 0xFFFFFFFF);
44
+ }
87
+ }
45
+
88
+
46
+ /* Fill memory */
89
+ entry_addr = table_entry_addr(s, &s->vpet, vpeid, &res);
47
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x01);
90
+ if (res != MEMTX_OK) {
48
+ for (i = 0; i < size / 4; i++) {
91
+ return false;
49
+ qtest_writel(qts, base + i * 4, i);
50
+ g_assert_cmpuint(qtest_readl(qts, base + i * 4), ==, i);
51
+ }
92
+ }
52
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
93
+ if (entry_addr == -1) {
94
+ /* No L2 table for this index: discard write and continue */
95
+ return true;
96
+ }
97
+ address_space_stq_le(as, entry_addr, vteval, MEMTXATTRS_UNSPECIFIED, &res);
98
+ return res == MEMTX_OK;
53
+}
99
+}
54
+
100
+
55
+static void test_nrf51_nvmc(void)
101
+static ItsCmdResult process_vmapp(GICv3ITSState *s, const uint64_t *cmdpkt)
56
+{
102
+{
57
+ uint32_t value;
103
+ VTEntry vte;
58
+ hwaddr i;
104
+ uint32_t vpeid;
59
+ QTestState *qts = qtest_init("-M microbit");
60
+
105
+
61
+ /* Test always ready */
106
+ if (!its_feature_virtual(s)) {
62
+ value = qtest_readl(qts, NRF51_NVMC_BASE + NRF51_NVMC_READY);
107
+ return CMD_CONTINUE;
63
+ g_assert_cmpuint(value & 0x01, ==, 0x01);
64
+
65
+ /* Test write-read config register */
66
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x03);
67
+ g_assert_cmpuint(qtest_readl(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG),
68
+ ==, 0x03);
69
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
70
+ g_assert_cmpuint(qtest_readl(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG),
71
+ ==, 0x00);
72
+
73
+ /* Test PCR0 */
74
+ fill_and_erase(qts, NRF51_FLASH_BASE, NRF51_PAGE_SIZE,
75
+ NRF51_NVMC_ERASEPCR0);
76
+ fill_and_erase(qts, NRF51_FLASH_BASE + NRF51_PAGE_SIZE,
77
+ NRF51_PAGE_SIZE, NRF51_NVMC_ERASEPCR0);
78
+
79
+ /* Test PCR1 */
80
+ fill_and_erase(qts, NRF51_FLASH_BASE, NRF51_PAGE_SIZE,
81
+ NRF51_NVMC_ERASEPCR1);
82
+ fill_and_erase(qts, NRF51_FLASH_BASE + NRF51_PAGE_SIZE,
83
+ NRF51_PAGE_SIZE, NRF51_NVMC_ERASEPCR1);
84
+
85
+ /* Erase all */
86
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
87
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_ERASEALL, 0x01);
88
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
89
+
90
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x01);
91
+ for (i = 0; i < FLASH_SIZE / 4; i++) {
92
+ qtest_writel(qts, NRF51_FLASH_BASE + i * 4, i);
93
+ g_assert_cmpuint(qtest_readl(qts, NRF51_FLASH_BASE + i * 4), ==, i);
94
+ }
95
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
96
+
97
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
98
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_ERASEALL, 0x01);
99
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
100
+
101
+ for (i = 0; i < FLASH_SIZE / 4; i++) {
102
+ g_assert_cmpuint(qtest_readl(qts, NRF51_FLASH_BASE + i * 4),
103
+ ==, 0xFFFFFFFF);
104
+ }
108
+ }
105
+
109
+
106
+ /* Erase UICR */
110
+ vpeid = FIELD_EX64(cmdpkt[1], VMAPP_1, VPEID);
107
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
111
+ vte.rdbase = FIELD_EX64(cmdpkt[2], VMAPP_2, RDBASE);
108
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_ERASEUICR, 0x01);
112
+ vte.valid = FIELD_EX64(cmdpkt[2], VMAPP_2, V);
109
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
113
+ vte.vptsize = FIELD_EX64(cmdpkt[3], VMAPP_3, VPTSIZE);
114
+ vte.vptaddr = FIELD_EX64(cmdpkt[3], VMAPP_3, VPTADDR);
110
+
115
+
111
+ for (i = 0; i < NRF51_UICR_SIZE / 4; i++) {
116
+ trace_gicv3_its_cmd_vmapp(vpeid, vte.rdbase, vte.valid,
112
+ g_assert_cmpuint(qtest_readl(qts, NRF51_UICR_BASE + i * 4),
117
+ vte.vptaddr, vte.vptsize);
113
+ ==, 0xFFFFFFFF);
118
+
119
+ /*
120
+ * For GICv4.0 the VPT_size field is only 5 bits, whereas we
121
+ * define our field macros to include the full GICv4.1 8 bits.
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
+ */
125
+ if (vte.vptsize > FIELD_EX64(s->typer, GITS_TYPER, IDBITS)) {
126
+ qemu_log_mask(LOG_GUEST_ERROR,
127
+ "%s: invalid VPT_size 0x%x\n", __func__, vte.vptsize);
128
+ return CMD_CONTINUE;
114
+ }
129
+ }
115
+
130
+
116
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x01);
131
+ if (vte.valid && vte.rdbase >= s->gicv3->num_cpu) {
117
+ for (i = 0; i < NRF51_UICR_SIZE / 4; i++) {
132
+ qemu_log_mask(LOG_GUEST_ERROR,
118
+ qtest_writel(qts, NRF51_UICR_BASE + i * 4, i);
133
+ "%s: invalid rdbase 0x%x\n", __func__, vte.rdbase);
119
+ g_assert_cmpuint(qtest_readl(qts, NRF51_UICR_BASE + i * 4), ==, i);
134
+ return CMD_CONTINUE;
120
+ }
121
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
122
+
123
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
124
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_ERASEUICR, 0x01);
125
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
126
+
127
+ for (i = 0; i < NRF51_UICR_SIZE / 4; i++) {
128
+ g_assert_cmpuint(qtest_readl(qts, NRF51_UICR_BASE + i * 4),
129
+ ==, 0xFFFFFFFF);
130
+ }
135
+ }
131
+
136
+
132
+ qtest_quit(qts);
137
+ if (vpeid >= s->vpet.num_entries) {
138
+ qemu_log_mask(LOG_GUEST_ERROR,
139
+ "%s: VPEID 0x%x out of range (must be less than 0x%x)\n",
140
+ __func__, vpeid, s->vpet.num_entries);
141
+ return CMD_CONTINUE;
142
+ }
143
+
144
+ return update_vte(s, vpeid, &vte) ? CMD_CONTINUE : CMD_STALL;
133
+}
145
+}
134
+
146
+
135
static void test_nrf51_gpio(void)
147
/*
136
{
148
* Current implementation blocks until all
137
size_t i;
149
* commands are processed
138
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
150
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
139
151
case GITS_CMD_VMAPI:
140
qtest_add_func("/microbit/nrf51/uart", test_nrf51_uart);
152
result = process_vmapti(s, cmdpkt, true);
141
qtest_add_func("/microbit/nrf51/gpio", test_nrf51_gpio);
153
break;
142
+ qtest_add_func("/microbit/nrf51/nvmc", test_nrf51_nvmc);
154
+ case GITS_CMD_VMAPP:
143
qtest_add_func("/microbit/nrf51/timer", test_nrf51_timer);
155
+ result = process_vmapp(s, cmdpkt);
144
qtest_add_func("/microbit/microbit/i2c", test_microbit_i2c);
156
+ break;
145
157
default:
158
trace_gicv3_its_cmd_unknown(cmd);
159
break;
160
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
161
index XXXXXXX..XXXXXXX 100644
162
--- a/hw/intc/trace-events
163
+++ b/hw/intc/trace-events
164
@@ -XXX,XX +XXX,XX @@ gicv3_its_cmd_movall(uint64_t rd1, uint64_t rd2) "GICv3 ITS: command MOVALL RDba
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"
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"
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"
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"
169
gicv3_its_cmd_unknown(unsigned cmd) "GICv3 ITS: unknown command 0x%x"
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"
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"
172
@@ -XXX,XX +XXX,XX @@ gicv3_its_ite_write(uint64_t ittaddr, uint32_t eventid, int valid, int inttype,
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
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
175
gicv3_its_dte_read_fault(uint32_t devid) "GICv3 ITS: Device Table read for DeviceID 0x%x: faulted"
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"
177
178
# armv7m_nvic.c
179
nvic_recompute_state(int vectpending, int vectpending_prio, int exception_prio) "NVIC state recomputed: vectpending %d vectpending_prio %d exception_prio %d"
146
--
180
--
147
2.20.1
181
2.25.1
148
149
diff view generated by jsdifflib
1
Rename various internal uses of 'iotkit' in hw/arm/iotkit.c to
1
In the ItsCmdResult enum, we currently distinguish only CMD_STALL
2
'armsse', for consistency. The remaining occurences are:
2
(failure, stall processing of the command queue) and CMD_CONTINUE
3
* related to the devices TYPE_IOTKIT_SYSCTL, TYPE_IOTKIT_SYSINFO,
3
(keep processing the queue), and we use the latter both for "there
4
etc, which this refactor is not touching
4
was a parameter error, go on to the next command" and "the command
5
* references that apply specifically to the IoTKit (like
5
succeeded, go on to the next command". Sometimes we would like to
6
the lack of a private CPU region)
6
distinguish those two cases, so add CMD_CONTINUE_OK to the enum to
7
* the vmstate, which keeps its old "iotkit" name for
7
represent the success situation, and use it in the relevant places.
8
migration compatibility reasons
9
8
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20190121185118.18550-7-peter.maydell@linaro.org
11
Message-id: 20220408141550.1271295-11-peter.maydell@linaro.org
14
---
12
---
15
hw/arm/iotkit.c | 68 ++++++++++++++++++++++++-------------------------
13
hw/intc/arm_gicv3_its.c | 29 ++++++++++++++++-------------
16
1 file changed, 34 insertions(+), 34 deletions(-)
14
1 file changed, 16 insertions(+), 13 deletions(-)
17
15
18
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
16
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/iotkit.c
18
--- a/hw/intc/arm_gicv3_its.c
21
+++ b/hw/arm/iotkit.c
19
+++ b/hw/intc/arm_gicv3_its.c
22
@@ -XXX,XX +XXX,XX @@ static void nsccfg_handler(void *opaque, int n, int level)
20
@@ -XXX,XX +XXX,XX @@ typedef struct VTEntry {
23
s->nsccfg = level;
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;
24
}
44
}
25
45
26
-static void iotkit_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
46
static ItsCmdResult process_its_cmd(GICv3ITSState *s, const uint64_t *cmdpkt,
27
+static void armsse_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
47
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
28
{
48
ite.icid = icid;
29
/* Each of the 4 AHB and 4 APB PPCs that might be present in a
49
ite.doorbell = INTID_SPURIOUS;
30
* system using the ARMSSE has a collection of control lines which
50
ite.vpeid = 0;
31
@@ -XXX,XX +XXX,XX @@ static void iotkit_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
51
- return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE : CMD_STALL;
32
* code using the ARMSSE can wire them up to the PPCs.
52
+ return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE_OK : CMD_STALL;
33
*/
34
SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum];
35
- DeviceState *iotkitdev = DEVICE(s);
36
+ DeviceState *armssedev = DEVICE(s);
37
DeviceState *dev_secctl = DEVICE(&s->secctl);
38
DeviceState *dev_splitter = DEVICE(splitter);
39
char *name;
40
41
name = g_strdup_printf("%s_nonsec", ppcname);
42
- qdev_pass_gpios(dev_secctl, iotkitdev, name);
43
+ qdev_pass_gpios(dev_secctl, armssedev, name);
44
g_free(name);
45
name = g_strdup_printf("%s_ap", ppcname);
46
- qdev_pass_gpios(dev_secctl, iotkitdev, name);
47
+ qdev_pass_gpios(dev_secctl, armssedev, name);
48
g_free(name);
49
name = g_strdup_printf("%s_irq_enable", ppcname);
50
- qdev_pass_gpios(dev_secctl, iotkitdev, name);
51
+ qdev_pass_gpios(dev_secctl, armssedev, name);
52
g_free(name);
53
name = g_strdup_printf("%s_irq_clear", ppcname);
54
- qdev_pass_gpios(dev_secctl, iotkitdev, name);
55
+ qdev_pass_gpios(dev_secctl, armssedev, name);
56
g_free(name);
57
58
/* irq_status is a little more tricky, because we need to
59
@@ -XXX,XX +XXX,XX @@ static void iotkit_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
60
qdev_connect_gpio_out(dev_splitter, 1,
61
qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), ppcnum));
62
s->irq_status_in[ppcnum] = qdev_get_gpio_in(dev_splitter, 0);
63
- qdev_init_gpio_in_named_with_opaque(iotkitdev, irq_status_forwarder,
64
+ qdev_init_gpio_in_named_with_opaque(armssedev, irq_status_forwarder,
65
s->irq_status_in[ppcnum], name, 1);
66
g_free(name);
67
}
53
}
68
54
69
-static void iotkit_forward_sec_resp_cfg(ARMSSE *s)
55
static ItsCmdResult process_vmapti(GICv3ITSState *s, const uint64_t *cmdpkt,
70
+static void armsse_forward_sec_resp_cfg(ARMSSE *s)
56
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_vmapti(GICv3ITSState *s, const uint64_t *cmdpkt,
71
{
57
ite.icid = 0;
72
/* Forward the 3rd output from the splitter device as a
58
ite.doorbell = doorbell;
73
- * named GPIO output of the iotkit object.
59
ite.vpeid = vpeid;
74
+ * named GPIO output of the armsse object.
60
- return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE : CMD_STALL;
75
*/
61
+ return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE_OK : CMD_STALL;
76
DeviceState *dev = DEVICE(s);
77
DeviceState *dev_splitter = DEVICE(&s->sec_resp_splitter);
78
@@ -XXX,XX +XXX,XX @@ static void iotkit_forward_sec_resp_cfg(ARMSSE *s)
79
qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
80
}
62
}
81
63
82
-static void iotkit_init(Object *obj)
64
/*
83
+static void armsse_init(Object *obj)
65
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt)
84
{
66
return CMD_CONTINUE;
85
ARMSSE *s = ARMSSE(obj);
86
int i;
87
88
- memory_region_init(&s->container, obj, "iotkit-container", UINT64_MAX);
89
+ memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
90
91
sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
92
TYPE_ARMV7M);
93
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
94
sizeof(s->nswatchdog), TYPE_CMSDK_APB_WATCHDOG);
95
sysbus_init_child_obj(obj, "swatchdog", &s->swatchdog,
96
sizeof(s->swatchdog), TYPE_CMSDK_APB_WATCHDOG);
97
- sysbus_init_child_obj(obj, "iotkit-sysctl", &s->sysctl,
98
+ sysbus_init_child_obj(obj, "armsse-sysctl", &s->sysctl,
99
sizeof(s->sysctl), TYPE_IOTKIT_SYSCTL);
100
- sysbus_init_child_obj(obj, "iotkit-sysinfo", &s->sysinfo,
101
+ sysbus_init_child_obj(obj, "armsse-sysinfo", &s->sysinfo,
102
sizeof(s->sysinfo), TYPE_IOTKIT_SYSINFO);
103
object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
104
sizeof(s->nmi_orgate), TYPE_OR_IRQ,
105
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
106
}
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;
107
}
71
}
108
72
109
-static void iotkit_exp_irq(void *opaque, int n, int level)
73
/*
110
+static void armsse_exp_irq(void *opaque, int n, int level)
74
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapd(GICv3ITSState *s, const uint64_t *cmdpkt)
111
{
75
return CMD_CONTINUE;
112
ARMSSE *s = ARMSSE(opaque);
76
}
113
77
114
qemu_set_irq(s->exp_irqs[n], level);
78
- return update_dte(s, devid, &dte) ? CMD_CONTINUE : CMD_STALL;
79
+ return update_dte(s, devid, &dte) ? CMD_CONTINUE_OK : CMD_STALL;
115
}
80
}
116
81
117
-static void iotkit_mpcexp_status(void *opaque, int n, int level)
82
static ItsCmdResult process_movall(GICv3ITSState *s, const uint64_t *cmdpkt)
118
+static void armsse_mpcexp_status(void *opaque, int n, int level)
83
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movall(GICv3ITSState *s, const uint64_t *cmdpkt)
119
{
84
120
ARMSSE *s = ARMSSE(opaque);
85
if (rd1 == rd2) {
121
qemu_set_irq(s->mpcexp_status_in[n], level);
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;
122
}
96
}
123
97
124
-static void iotkit_realize(DeviceState *dev, Error **errp)
98
static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
125
+static void armsse_realize(DeviceState *dev, Error **errp)
99
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
126
{
100
127
ARMSSE *s = ARMSSE(dev);
101
/* Update the ICID field in the interrupt translation table entry */
128
int i;
102
old_ite.icid = new_icid;
129
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
103
- return update_ite(s, eventid, &dte, &old_ite) ? CMD_CONTINUE : CMD_STALL;
130
for (i = 0; i < s->exp_numirq; i++) {
104
+ return update_ite(s, eventid, &dte, &old_ite) ? CMD_CONTINUE_OK : CMD_STALL;
131
s->exp_irqs[i] = qdev_get_gpio_in(DEVICE(&s->armv7m), i + 32);
105
}
106
107
/*
108
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_vmapp(GICv3ITSState *s, const uint64_t *cmdpkt)
109
return CMD_CONTINUE;
132
}
110
}
133
- qdev_init_gpio_in_named(dev, iotkit_exp_irq, "EXP_IRQ", s->exp_numirq);
111
134
+ qdev_init_gpio_in_named(dev, armsse_exp_irq, "EXP_IRQ", s->exp_numirq);
112
- return update_vte(s, vpeid, &vte) ? CMD_CONTINUE : CMD_STALL;
135
113
+ return update_vte(s, vpeid, &vte) ? CMD_CONTINUE_OK : CMD_STALL;
136
/* Set up the big aliases first */
114
}
137
make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
115
138
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
116
/*
139
qdev_get_gpio_in(dev_splitter, 0));
117
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
140
141
/* This RAM lives behind the Memory Protection Controller */
142
- memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &err);
143
+ memory_region_init_ram(&s->sram0, NULL, "armsse.sram0", 0x00008000, &err);
144
if (err) {
145
error_propagate(errp, err);
146
return;
147
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
148
for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
149
char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
150
151
- iotkit_forward_ppc(s, ppcname, i);
152
+ armsse_forward_ppc(s, ppcname, i);
153
g_free(ppcname);
154
}
118
}
155
119
156
for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
120
while (wr_offset != rd_offset) {
157
char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
121
- ItsCmdResult result = CMD_CONTINUE;
158
122
+ ItsCmdResult result = CMD_CONTINUE_OK;
159
- iotkit_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
123
void *hostmem;
160
+ armsse_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
124
hwaddr buflen;
161
g_free(ppcname);
125
uint64_t cmdpkt[GITS_CMDQ_ENTRY_WORDS];
162
}
126
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
163
127
trace_gicv3_its_cmd_unknown(cmd);
164
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
128
break;
165
/* Create GPIO inputs which will pass the line state for our
129
}
166
* mpcexp_irq inputs to the correct splitter devices.
130
- if (result == CMD_CONTINUE) {
167
*/
131
+ if (result != CMD_STALL) {
168
- qdev_init_gpio_in_named(dev, iotkit_mpcexp_status, "mpcexp_status",
132
+ /* CMD_CONTINUE or CMD_CONTINUE_OK */
169
+ qdev_init_gpio_in_named(dev, armsse_mpcexp_status, "mpcexp_status",
133
rd_offset++;
170
IOTS_NUM_EXP_MPC);
134
rd_offset %= s->cq.num_entries;
171
135
s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset);
172
- iotkit_forward_sec_resp_cfg(s);
173
+ armsse_forward_sec_resp_cfg(s);
174
175
/* Forward the MSC related signals */
176
qdev_pass_gpios(dev_secctl, dev, "mscexp_status");
177
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
178
system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
179
}
180
181
-static void iotkit_idau_check(IDAUInterface *ii, uint32_t address,
182
+static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
183
int *iregion, bool *exempt, bool *ns, bool *nsc)
184
{
185
/*
186
@@ -XXX,XX +XXX,XX @@ static void iotkit_idau_check(IDAUInterface *ii, uint32_t address,
187
*iregion = region;
188
}
189
190
-static const VMStateDescription iotkit_vmstate = {
191
+static const VMStateDescription armsse_vmstate = {
192
.name = "iotkit",
193
.version_id = 1,
194
.minimum_version_id = 1,
195
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_vmstate = {
196
}
197
};
198
199
-static Property iotkit_properties[] = {
200
+static Property armsse_properties[] = {
201
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
202
MemoryRegion *),
203
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
204
@@ -XXX,XX +XXX,XX @@ static Property iotkit_properties[] = {
205
DEFINE_PROP_END_OF_LIST()
206
};
207
208
-static void iotkit_reset(DeviceState *dev)
209
+static void armsse_reset(DeviceState *dev)
210
{
211
ARMSSE *s = ARMSSE(dev);
212
213
s->nsccfg = 0;
214
}
215
216
-static void iotkit_class_init(ObjectClass *klass, void *data)
217
+static void armsse_class_init(ObjectClass *klass, void *data)
218
{
219
DeviceClass *dc = DEVICE_CLASS(klass);
220
IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
221
ARMSSEClass *asc = ARMSSE_CLASS(klass);
222
223
- dc->realize = iotkit_realize;
224
- dc->vmsd = &iotkit_vmstate;
225
- dc->props = iotkit_properties;
226
- dc->reset = iotkit_reset;
227
- iic->check = iotkit_idau_check;
228
+ dc->realize = armsse_realize;
229
+ dc->vmsd = &armsse_vmstate;
230
+ dc->props = armsse_properties;
231
+ dc->reset = armsse_reset;
232
+ iic->check = armsse_idau_check;
233
asc->info = data;
234
}
235
236
@@ -XXX,XX +XXX,XX @@ static const TypeInfo armsse_info = {
237
.name = TYPE_ARMSSE,
238
.parent = TYPE_SYS_BUS_DEVICE,
239
.instance_size = sizeof(ARMSSE),
240
- .instance_init = iotkit_init,
241
+ .instance_init = armsse_init,
242
.abstract = true,
243
.interfaces = (InterfaceInfo[]) {
244
{ TYPE_IDAU_INTERFACE },
245
@@ -XXX,XX +XXX,XX @@ static void armsse_register_types(void)
246
TypeInfo ti = {
247
.name = armsse_variants[i].name,
248
.parent = TYPE_ARMSSE,
249
- .class_init = iotkit_class_init,
250
+ .class_init = armsse_class_init,
251
.class_data = (void *)&armsse_variants[i],
252
};
253
type_register(&ti);
254
--
136
--
255
2.20.1
137
2.25.1
256
257
diff view generated by jsdifflib
1
In the AdvSIMD load/store single structure encodings, the
1
The operation of finding an interrupt table entry given a (DeviceID,
2
non-post-indexed case should have zeroes in [20:16] (which is the
2
EventID) pair is necessary in multiple different ITS commands. The
3
Rm field for the post-indexed case). Bit 31 must also be zero
3
process requires first using the DeviceID as an index into the device
4
(a check we got right in ldst_multiple but not here). Correctly
4
table to find the DTE, and then useng the EventID as an index into
5
UNDEF these unallocated encodings.
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.
6
8
7
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
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
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20190125182626.9221-5-peter.maydell@linaro.org
16
Message-id: 20220408141550.1271295-12-peter.maydell@linaro.org
11
---
17
---
12
target/arm/translate-a64.c | 11 ++++++++++-
18
hw/intc/arm_gicv3_its.c | 124 +++++++++++++++++++++-------------------
13
1 file changed, 10 insertions(+), 1 deletion(-)
19
1 file changed, 64 insertions(+), 60 deletions(-)
14
20
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
21
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
16
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
23
--- a/hw/intc/arm_gicv3_its.c
18
+++ b/target/arm/translate-a64.c
24
+++ b/hw/intc/arm_gicv3_its.c
19
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
25
@@ -XXX,XX +XXX,XX @@ out:
20
{
26
return res;
21
int rt = extract32(insn, 0, 5);
27
}
22
int rn = extract32(insn, 5, 5);
28
23
+ int rm = extract32(insn, 16, 5);
29
+/*
24
int size = extract32(insn, 10, 2);
30
+ * Given a (DeviceID, EventID), look up the corresponding ITE, including
25
int S = extract32(insn, 12, 1);
31
+ * checking for the various invalid-value cases. If we find a valid ITE,
26
int opc = extract32(insn, 13, 3);
32
+ * fill in @ite and @dte and return CMD_CONTINUE_OK. Otherwise return
27
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
33
+ * CMD_STALL or CMD_CONTINUE as appropriate (and the contents of @ite
28
int ebytes, xs;
34
+ * should not be relied on).
29
TCGv_i64 tcg_addr, tcg_rn, tcg_ebytes;
35
+ *
30
36
+ * The string @who is purely for the LOG_GUEST_ERROR messages,
31
+ if (extract32(insn, 31, 1)) {
37
+ * and should indicate the name of the calling function or similar.
32
+ unallocated_encoding(s);
38
+ */
33
+ return;
39
+static ItsCmdResult lookup_ite(GICv3ITSState *s, const char *who,
34
+ }
40
+ uint32_t devid, uint32_t eventid, ITEntry *ite,
35
+ if (!is_postidx && rm != 0) {
41
+ DTEntry *dte)
36
+ unallocated_encoding(s);
42
+{
37
+ return;
43
+ uint64_t num_eventids;
44
+
45
+ if (devid >= s->dt.num_entries) {
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;
38
+ }
50
+ }
39
+
51
+
40
switch (scale) {
52
+ if (get_dte(s, devid, dte) != MEMTX_OK) {
41
case 3:
53
+ return CMD_STALL;
42
if (!is_load || S) {
54
+ }
43
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
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
+}
82
+
83
/*
84
* This function handles the processing of following commands based on
85
* the ItsCmdType parameter passed:-
86
@@ -XXX,XX +XXX,XX @@ out:
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;
44
}
104
}
45
105
46
if (is_postidx) {
106
- if (get_dte(s, devid, &dte) != MEMTX_OK) {
47
- int rm = extract32(insn, 16, 5);
107
- return CMD_STALL;
48
if (rm == 31) {
108
- }
49
tcg_gen_mov_i64(tcg_rn, tcg_addr);
109
- if (!dte.valid) {
50
} else {
110
- qemu_log_mask(LOG_GUEST_ERROR,
111
- "%s: invalid command attributes: "
112
- "invalid dte for %d\n", __func__, devid);
113
- return CMD_CONTINUE;
114
- }
115
-
116
- num_eventids = 1ULL << (dte.size + 1);
117
- if (eventid >= num_eventids) {
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
- }
124
-
125
- if (get_ite(s, eventid, &dte, &ite) != MEMTX_OK) {
126
- return CMD_STALL;
127
- }
128
-
129
- if (!ite.valid || ite.inttype != ITE_INTTYPE_PHYSICAL) {
130
+ if (ite.inttype != ITE_INTTYPE_PHYSICAL) {
131
qemu_log_mask(LOG_GUEST_ERROR,
132
"%s: invalid command attributes: invalid ITE\n",
133
__func__);
134
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
135
{
136
uint32_t devid, eventid;
137
uint16_t new_icid;
138
- uint64_t num_eventids;
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
}
162
163
- if (!dte.valid) {
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__);
51
--
188
--
52
2.20.1
189
2.25.1
53
54
diff view generated by jsdifflib
1
The SSE-200 has four banks of SRAM, each with its own
1
Factor out the sequence of looking up a CTE from an ICID including
2
Memory Protection Controller, where the IoTKit has only one.
2
the validity and error checks.
3
Make the number of SRAM banks a field in ARMSSEInfo.
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: 20190121185118.18550-10-peter.maydell@linaro.org
6
Message-id: 20220408141550.1271295-13-peter.maydell@linaro.org
8
---
7
---
9
include/hw/arm/armsse.h | 9 +++--
8
hw/intc/arm_gicv3_its.c | 109 ++++++++++++++--------------------------
10
hw/arm/armsse.c | 78 ++++++++++++++++++++++++++---------------
9
1 file changed, 39 insertions(+), 70 deletions(-)
11
2 files changed, 56 insertions(+), 31 deletions(-)
12
10
13
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
11
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/arm/armsse.h
13
--- a/hw/intc/arm_gicv3_its.c
16
+++ b/include/hw/arm/armsse.h
14
+++ b/hw/intc/arm_gicv3_its.c
17
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult lookup_ite(GICv3ITSState *s, const char *who,
18
#define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
16
return CMD_CONTINUE_OK;
19
#define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
17
}
20
18
21
+#define MAX_SRAM_BANKS 4
19
+/*
22
+#if MAX_SRAM_BANKS > IOTS_NUM_MPC
20
+ * Given an ICID, look up the corresponding CTE, including checking for various
23
+#error Too many SRAM banks
21
+ * invalid-value cases. If we find a valid CTE, fill in @cte and return
24
+#endif
22
+ * CMD_CONTINUE_OK; otherwise return CMD_STALL or CMD_CONTINUE (and the
23
+ * contents of @cte should not be relied on).
24
+ *
25
+ * The string @who is purely for the LOG_GUEST_ERROR messages,
26
+ * and should indicate the name of the calling function or similar.
27
+ */
28
+static ItsCmdResult lookup_cte(GICv3ITSState *s, const char *who,
29
+ uint32_t icid, CTEntry *cte)
30
+{
31
+ if (icid >= s->ct.num_entries) {
32
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid ICID 0x%x\n", who, icid);
33
+ return CMD_CONTINUE;
34
+ }
35
+ if (get_cte(s, icid, cte) != MEMTX_OK) {
36
+ return CMD_STALL;
37
+ }
38
+ if (!cte->valid) {
39
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid CTE\n", who);
40
+ return CMD_CONTINUE;
41
+ }
42
+ if (cte->rdbase >= s->gicv3->num_cpu) {
43
+ return CMD_CONTINUE;
44
+ }
45
+ return CMD_CONTINUE_OK;
46
+}
25
+
47
+
26
typedef struct ARMSSE {
27
/*< private >*/
28
SysBusDevice parent_obj;
29
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
30
IoTKitSecCtl secctl;
31
TZPPC apb_ppc0;
32
TZPPC apb_ppc1;
33
- TZMPC mpc;
34
+ TZMPC mpc[IOTS_NUM_MPC];
35
CMSDKAPBTIMER timer0;
36
CMSDKAPBTIMER timer1;
37
CMSDKAPBTIMER s32ktimer;
38
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
39
MemoryRegion alias1;
40
MemoryRegion alias2;
41
MemoryRegion alias3;
42
- MemoryRegion sram0;
43
+ MemoryRegion sram[MAX_SRAM_BANKS];
44
45
qemu_irq *exp_irqs;
46
qemu_irq ppc0_irq;
47
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/arm/armsse.c
50
+++ b/hw/arm/armsse.c
51
@@ -XXX,XX +XXX,XX @@
52
53
struct ARMSSEInfo {
54
const char *name;
55
+ int sram_banks;
56
};
57
58
static const ARMSSEInfo armsse_variants[] = {
59
{
60
.name = TYPE_IOTKIT,
61
+ .sram_banks = 1,
62
},
63
};
64
65
@@ -XXX,XX +XXX,XX @@ static void armsse_forward_sec_resp_cfg(ARMSSE *s)
66
static void armsse_init(Object *obj)
67
{
68
ARMSSE *s = ARMSSE(obj);
69
+ ARMSSEClass *asc = ARMSSE_GET_CLASS(obj);
70
+ const ARMSSEInfo *info = asc->info;
71
int i;
72
73
+ assert(info->sram_banks <= MAX_SRAM_BANKS);
74
+
48
+
75
memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
49
/*
76
50
* This function handles the processing of following commands based on
77
sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
51
* the ItsCmdType parameter passed:-
78
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
52
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
79
TYPE_TZ_PPC);
53
return CMD_CONTINUE;
80
sysbus_init_child_obj(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
81
TYPE_TZ_PPC);
82
- sysbus_init_child_obj(obj, "mpc", &s->mpc, sizeof(s->mpc), TYPE_TZ_MPC);
83
+ for (i = 0; i < info->sram_banks; i++) {
84
+ char *name = g_strdup_printf("mpc%d", i);
85
+ sysbus_init_child_obj(obj, name, &s->mpc[i],
86
+ sizeof(s->mpc[i]), TYPE_TZ_MPC);
87
+ g_free(name);
88
+ }
89
object_initialize_child(obj, "mpc-irq-orgate", &s->mpc_irq_orgate,
90
sizeof(s->mpc_irq_orgate), TYPE_OR_IRQ,
91
&error_abort, NULL);
92
93
- for (i = 0; i < IOTS_NUM_EXP_MPC + 1; i++) {
94
+ for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) {
95
char *name = g_strdup_printf("mpc-irq-splitter-%d", i);
96
SplitIRQ *splitter = &s->mpc_irq_splitter[i];
97
98
@@ -XXX,XX +XXX,XX @@ static void armsse_mpcexp_status(void *opaque, int n, int level)
99
static void armsse_realize(DeviceState *dev, Error **errp)
100
{
101
ARMSSE *s = ARMSSE(dev);
102
+ ARMSSEClass *asc = ARMSSE_GET_CLASS(dev);
103
+ const ARMSSEInfo *info = asc->info;
104
int i;
105
MemoryRegion *mr;
106
Error *err = NULL;
107
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
108
qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0,
109
qdev_get_gpio_in(dev_splitter, 0));
110
111
- /* This RAM lives behind the Memory Protection Controller */
112
- memory_region_init_ram(&s->sram0, NULL, "armsse.sram0", 0x00008000, &err);
113
- if (err) {
114
- error_propagate(errp, err);
115
- return;
116
+ /* Each SRAM bank lives behind its own Memory Protection Controller */
117
+ for (i = 0; i < info->sram_banks; i++) {
118
+ char *ramname = g_strdup_printf("armsse.sram%d", i);
119
+ SysBusDevice *sbd_mpc;
120
+
121
+ memory_region_init_ram(&s->sram[i], NULL, ramname, 0x00008000, &err);
122
+ g_free(ramname);
123
+ if (err) {
124
+ error_propagate(errp, err);
125
+ return;
126
+ }
127
+ object_property_set_link(OBJECT(&s->mpc[i]), OBJECT(&s->sram[i]),
128
+ "downstream", &err);
129
+ if (err) {
130
+ error_propagate(errp, err);
131
+ return;
132
+ }
133
+ object_property_set_bool(OBJECT(&s->mpc[i]), true, "realized", &err);
134
+ if (err) {
135
+ error_propagate(errp, err);
136
+ return;
137
+ }
138
+ /* Map the upstream end of the MPC into the right place... */
139
+ sbd_mpc = SYS_BUS_DEVICE(&s->mpc[i]);
140
+ memory_region_add_subregion(&s->container, 0x20000000 + i * 0x8000,
141
+ sysbus_mmio_get_region(sbd_mpc, 1));
142
+ /* ...and its register interface */
143
+ memory_region_add_subregion(&s->container, 0x50083000 + i * 0x1000,
144
+ sysbus_mmio_get_region(sbd_mpc, 0));
145
}
54
}
146
- object_property_set_link(OBJECT(&s->mpc), OBJECT(&s->sram0),
55
147
- "downstream", &err);
56
- if (ite.icid >= s->ct.num_entries) {
148
- if (err) {
57
- qemu_log_mask(LOG_GUEST_ERROR,
149
- error_propagate(errp, err);
58
- "%s: invalid ICID 0x%x in ITE (table corrupted?)\n",
150
- return;
59
- __func__, ite.icid);
60
- return CMD_CONTINUE;
151
- }
61
- }
152
- object_property_set_bool(OBJECT(&s->mpc), true, "realized", &err);
62
-
153
- if (err) {
63
- if (get_cte(s, ite.icid, &cte) != MEMTX_OK) {
154
- error_propagate(errp, err);
64
- return CMD_STALL;
155
- return;
156
- }
65
- }
157
- /* Map the upstream end of the MPC into the right place... */
66
- if (!cte.valid) {
158
- memory_region_add_subregion(&s->container, 0x20000000,
67
- qemu_log_mask(LOG_GUEST_ERROR,
159
- sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc),
68
- "%s: invalid command attributes: invalid CTE\n",
160
- 1));
69
- __func__);
161
- /* ...and its register interface */
70
- return CMD_CONTINUE;
162
- memory_region_add_subregion(&s->container, 0x50083000,
71
- }
163
- sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc),
72
-
164
- 0));
73
- /*
165
74
- * Current implementation only supports rdbase == procnum
166
/* We must OR together lines from the MPC splitters to go to the NVIC */
75
- * Hence rdbase physical address is ignored
167
object_property_set_int(OBJECT(&s->mpc_irq_orgate),
76
- */
168
- IOTS_NUM_EXP_MPC + 1, "num-lines", &err);
77
- if (cte.rdbase >= s->gicv3->num_cpu) {
169
+ IOTS_NUM_EXP_MPC + info->sram_banks,
78
- return CMD_CONTINUE;
170
+ "num-lines", &err);
79
+ cmdres = lookup_cte(s, __func__, ite.icid, &cte);
171
if (err) {
80
+ if (cmdres != CMD_CONTINUE_OK) {
172
error_propagate(errp, err);
81
+ return cmdres;
173
return;
174
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
175
}
82
}
176
83
177
/* Wire up the splitters for the MPC IRQs */
84
if ((cmd == CLEAR) || (cmd == DISCARD)) {
178
- for (i = 0; i < IOTS_NUM_EXP_MPC + 1; i++) {
85
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
179
+ for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) {
86
return CMD_CONTINUE;
180
SplitIRQ *splitter = &s->mpc_irq_splitter[i];
87
}
181
DeviceState *dev_splitter = DEVICE(splitter);
88
182
89
- if (old_ite.icid >= s->ct.num_entries) {
183
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
90
- qemu_log_mask(LOG_GUEST_ERROR,
184
"mpcexp_status", i));
91
- "%s: invalid ICID 0x%x in ITE (table corrupted?)\n",
185
} else {
92
- __func__, old_ite.icid);
186
/* Splitter input is from our own MPC */
93
- return CMD_CONTINUE;
187
- qdev_connect_gpio_out_named(DEVICE(&s->mpc), "irq", 0,
94
+ cmdres = lookup_cte(s, __func__, old_ite.icid, &old_cte);
188
+ qdev_connect_gpio_out_named(DEVICE(&s->mpc[i - IOTS_NUM_EXP_MPC]),
95
+ if (cmdres != CMD_CONTINUE_OK) {
189
+ "irq", 0,
96
+ return cmdres;
190
qdev_get_gpio_in(dev_splitter, 0));
97
}
191
qdev_connect_gpio_out(dev_splitter, 0,
98
-
192
qdev_get_gpio_in_named(dev_secctl,
99
- if (new_icid >= s->ct.num_entries) {
100
- qemu_log_mask(LOG_GUEST_ERROR,
101
- "%s: invalid command attributes: ICID 0x%x\n",
102
- __func__, new_icid);
103
- return CMD_CONTINUE;
104
- }
105
-
106
- if (get_cte(s, old_ite.icid, &old_cte) != MEMTX_OK) {
107
- return CMD_STALL;
108
- }
109
- if (!old_cte.valid) {
110
- qemu_log_mask(LOG_GUEST_ERROR,
111
- "%s: invalid command attributes: "
112
- "invalid CTE for old ICID 0x%x\n",
113
- __func__, old_ite.icid);
114
- return CMD_CONTINUE;
115
- }
116
-
117
- if (get_cte(s, new_icid, &new_cte) != MEMTX_OK) {
118
- return CMD_STALL;
119
- }
120
- if (!new_cte.valid) {
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) {
193
--
146
--
194
2.20.1
147
2.25.1
195
196
diff view generated by jsdifflib
1
In the AdvSIMD load/store multiple structures encodings,
1
Split the part of process_its_cmd() which is specific to physical
2
the non-post-indexed case should have zeroes in [20:16]
2
interrupts into its own function. This is the part which starts by
3
(which is the Rm field for the post-indexed case).
3
taking the ICID and looking it up in the collection table. The
4
Correctly UNDEF the currently unallocated encodings which
4
handling of virtual interrupts is significantly different (involving
5
have non-zeroes in those bits.
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.
6
9
7
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
10
The code for handling the "remove mapping from ITE" for the DISCARD
11
command remains in process_its_cmd() because it is common to both
12
virtual and physical interrupts.
13
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20190125182626.9221-4-peter.maydell@linaro.org
16
Message-id: 20220408141550.1271295-14-peter.maydell@linaro.org
11
---
17
---
12
target/arm/translate-a64.c | 7 ++++++-
18
hw/intc/arm_gicv3_its.c | 51 ++++++++++++++++++++++++++---------------
13
1 file changed, 6 insertions(+), 1 deletion(-)
19
1 file changed, 33 insertions(+), 18 deletions(-)
14
20
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
21
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
16
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
23
--- a/hw/intc/arm_gicv3_its.c
18
+++ b/target/arm/translate-a64.c
24
+++ b/hw/intc/arm_gicv3_its.c
19
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
25
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult lookup_cte(GICv3ITSState *s, const char *who,
26
return CMD_CONTINUE_OK;
27
}
28
29
+static ItsCmdResult process_its_cmd_phys(GICv3ITSState *s, const ITEntry *ite,
30
+ int irqlevel)
31
+{
32
+ CTEntry cte;
33
+ ItsCmdResult cmdres;
34
+
35
+ cmdres = lookup_cte(s, __func__, ite->icid, &cte);
36
+ if (cmdres != CMD_CONTINUE_OK) {
37
+ return cmdres;
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)
20
{
47
{
21
int rt = extract32(insn, 0, 5);
48
DTEntry dte;
22
int rn = extract32(insn, 5, 5);
49
- CTEntry cte;
23
+ int rm = extract32(insn, 16, 5);
50
ITEntry ite;
24
int size = extract32(insn, 10, 2);
51
ItsCmdResult cmdres;
25
int opcode = extract32(insn, 12, 4);
52
+ int irqlevel;
26
bool is_store = !extract32(insn, 22, 1);
53
27
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
54
cmdres = lookup_ite(s, __func__, devid, eventid, &ite, &dte);
28
return;
55
if (cmdres != CMD_CONTINUE_OK) {
56
return cmdres;
29
}
57
}
30
58
31
+ if (!is_postidx && rm != 0) {
59
- if (ite.inttype != ITE_INTTYPE_PHYSICAL) {
32
+ unallocated_encoding(s);
60
- qemu_log_mask(LOG_GUEST_ERROR,
33
+ return;
61
- "%s: invalid command attributes: invalid ITE\n",
34
+ }
62
- __func__);
63
- return CMD_CONTINUE;
64
+ irqlevel = (cmd == CLEAR || cmd == DISCARD) ? 0 : 1;
35
+
65
+
36
/* From the shared decode logic */
66
+ switch (ite.inttype) {
37
switch (opcode) {
67
+ case ITE_INTTYPE_PHYSICAL:
38
case 0x0:
68
+ cmdres = process_its_cmd_phys(s, &ite, irqlevel);
39
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
69
+ break;
70
+ case ITE_INTTYPE_VIRTUAL:
71
+ if (!its_feature_virtual(s)) {
72
+ /* Can't happen unless guest is illegally writing to table memory */
73
+ qemu_log_mask(LOG_GUEST_ERROR,
74
+ "%s: invalid type %d in ITE (table corrupted?)\n",
75
+ __func__, ite.inttype);
76
+ return CMD_CONTINUE;
77
+ }
78
+ /* The GICv4 virtual interrupt handling will go here */
79
+ g_assert_not_reached();
80
+ default:
81
+ g_assert_not_reached();
40
}
82
}
41
83
42
if (is_postidx) {
84
- cmdres = lookup_cte(s, __func__, ite.icid, &cte);
43
- int rm = extract32(insn, 16, 5);
85
- if (cmdres != CMD_CONTINUE_OK) {
44
if (rm == 31) {
86
- return cmdres;
45
tcg_gen_mov_i64(tcg_rn, tcg_addr);
87
- }
46
} else {
88
-
89
- if ((cmd == CLEAR) || (cmd == DISCARD)) {
90
- gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], ite.intid, 0);
91
- } else {
92
- gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], ite.intid, 1);
93
- }
94
-
95
- if (cmd == DISCARD) {
96
+ if (cmdres == CMD_CONTINUE_OK && cmd == DISCARD) {
97
ITEntry ite = {};
98
/* remove mapping from interrupt translation table */
99
ite.valid = false;
47
--
100
--
48
2.20.1
101
2.25.1
49
50
diff view generated by jsdifflib
New patch
1
For GICv4, interrupt table entries read by process_its_cmd() may
2
indicate virtual LPIs which are to be directly injected into a VM.
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.
1
8
9
The redistributor half will be implemented in a later commit;
10
for now we just provide a stub function which does nothing.
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-15-peter.maydell@linaro.org
15
---
16
hw/intc/gicv3_internal.h | 17 +++++++
17
hw/intc/arm_gicv3_its.c | 99 +++++++++++++++++++++++++++++++++++++-
18
hw/intc/arm_gicv3_redist.c | 9 ++++
19
hw/intc/trace-events | 2 +
20
4 files changed, 125 insertions(+), 2 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 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
27
void gicv3_dist_set_irq(GICv3State *s, int irq, int level);
28
void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level);
29
void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level);
30
+/**
31
+ * gicv3_redist_process_vlpi:
32
+ * @cs: GICv3CPUState
33
+ * @irq: (virtual) interrupt number
34
+ * @vptaddr: (guest) address of VLPI table
35
+ * @doorbell: doorbell (physical) interrupt number (1023 for "no doorbell")
36
+ * @level: level to set @irq to
37
+ *
38
+ * Process a virtual LPI being directly injected by the ITS. This function
39
+ * will update the VLPI table specified by @vptaddr and @vptsize. If the
40
+ * vCPU corresponding to that VLPI table is currently running on
41
+ * the CPU associated with this redistributor, directly inject the VLPI
42
+ * @irq. If the vCPU is not running on this CPU, raise the doorbell
43
+ * interrupt instead.
44
+ */
45
+void gicv3_redist_process_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr,
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
52
--- a/hw/intc/arm_gicv3_its.c
53
+++ b/hw/intc/arm_gicv3_its.c
54
@@ -XXX,XX +XXX,XX @@ out:
55
return res;
56
}
57
58
+/*
59
+ * Read the vPE Table entry at index @vpeid. On success (including
60
+ * successfully determining that there is no valid entry for this index),
61
+ * we return MEMTX_OK and populate the VTEntry struct accordingly.
62
+ * If there is an error reading memory then we return the error code.
63
+ */
64
+static MemTxResult get_vte(GICv3ITSState *s, uint32_t vpeid, VTEntry *vte)
65
+{
66
+ MemTxResult res = MEMTX_OK;
67
+ AddressSpace *as = &s->gicv3->dma_as;
68
+ uint64_t entry_addr = table_entry_addr(s, &s->vpet, vpeid, &res);
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
+ }
76
+ vteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res);
77
+ if (res != MEMTX_OK) {
78
+ goto out;
79
+ }
80
+ vte->valid = FIELD_EX64(vteval, VTE, VALID);
81
+ vte->vptsize = FIELD_EX64(vteval, VTE, VPTSIZE);
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
+}
93
+
94
/*
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
+{
113
+ if (vpeid >= s->vpet.num_entries) {
114
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid VPEID 0x%x\n", who, vpeid);
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
+}
132
+
133
static ItsCmdResult process_its_cmd_phys(GICv3ITSState *s, const ITEntry *ite,
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
+{
192
+ /*
193
+ * The redistributor handling for being handed a VLPI by the ITS
194
+ * will be added in a subsequent commit.
195
+ */
196
+}
197
+
198
void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level)
199
{
200
/* Update redistributor state for a change in an external PPI input line */
201
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
202
index XXXXXXX..XXXXXXX 100644
203
--- a/hw/intc/trace-events
204
+++ b/hw/intc/trace-events
205
@@ -XXX,XX +XXX,XX @@ gicv3_its_ite_write(uint64_t ittaddr, uint32_t eventid, int valid, int inttype,
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
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
--
215
2.25.1
diff view generated by jsdifflib
1
Instantiate a copy of the CPU_IDENTITY register block for each CPU
1
The GICv4 ITS VMOVP command's semantics require it to perform the
2
in an SSE-200.
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
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.
3
17
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20190121185118.18550-21-peter.maydell@linaro.org
20
Message-id: 20220408141550.1271295-16-peter.maydell@linaro.org
7
---
21
---
8
include/hw/arm/armsse.h | 3 +++
22
hw/intc/gicv3_internal.h | 9 +++++++++
9
hw/arm/armsse.c | 28 ++++++++++++++++++++++++++++
23
include/hw/intc/arm_gicv3_common.h | 2 ++
10
2 files changed, 31 insertions(+)
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(+)
11
28
12
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
29
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
13
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/armsse.h
31
--- a/hw/intc/gicv3_internal.h
15
+++ b/include/hw/arm/armsse.h
32
+++ b/hw/intc/gicv3_internal.h
16
@@ -XXX,XX +XXX,XX @@
33
@@ -XXX,XX +XXX,XX @@ static inline void gicv3_cache_all_target_cpustates(GICv3State *s)
17
#include "hw/watchdog/cmsdk-apb-watchdog.h"
34
18
#include "hw/misc/iotkit-sysctl.h"
35
void gicv3_set_gicv3state(CPUState *cpu, GICv3CPUState *s);
19
#include "hw/misc/iotkit-sysinfo.h"
36
20
+#include "hw/misc/armsse-cpuid.h"
37
+/*
21
#include "hw/misc/unimp.h"
38
+ * The ITS should call this when it is realized to add itself
22
#include "hw/or-irq.h"
39
+ * to its GIC's list of connected ITSes.
23
#include "hw/core/split-irq.h"
40
+ */
24
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
41
+static inline void gicv3_add_its(GICv3State *s, DeviceState *its)
25
UnimplementedDeviceState cachectrl[SSE_MAX_CPUS];
42
+{
26
UnimplementedDeviceState cpusecctrl[SSE_MAX_CPUS];
43
+ g_ptr_array_add(s->itslist, its);
27
44
+}
28
+ ARMSSECPUID cpuid[SSE_MAX_CPUS];
29
+
45
+
30
/*
46
#endif /* QEMU_ARM_GICV3_INTERNAL_H */
31
* 'container' holds all devices seen by all CPUs.
47
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
32
* 'cpu_container[i]' is the view that CPU i has: this has the
33
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
34
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/armsse.c
49
--- a/include/hw/intc/arm_gicv3_common.h
36
+++ b/hw/arm/armsse.c
50
+++ b/include/hw/intc/arm_gicv3_common.h
37
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
51
@@ -XXX,XX +XXX,XX @@ struct GICv3State {
38
bool has_ppus;
52
uint32_t gicd_nsacr[DIV_ROUND_UP(GICV3_MAXIRQ, 16)];
39
bool has_cachectrl;
53
40
bool has_cpusecctrl;
54
GICv3CPUState *cpu;
41
+ bool has_cpuid;
55
+ /* List of all ITSes connected to this GIC */
56
+ GPtrArray *itslist;
42
};
57
};
43
58
44
static const ARMSSEInfo armsse_variants[] = {
59
#define GICV3_BITMAP_ACCESSORS(BMP) \
45
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
60
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
46
.has_ppus = false,
61
index XXXXXXX..XXXXXXX 100644
47
.has_cachectrl = false,
62
--- a/hw/intc/arm_gicv3_common.c
48
.has_cpusecctrl = false,
63
+++ b/hw/intc/arm_gicv3_common.c
49
+ .has_cpuid = false,
64
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
50
},
65
cpuidx += s->redist_region_count[i];
51
};
66
s->cpu[cpuidx - 1].gicr_typer |= GICR_TYPER_LAST;
52
67
}
53
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
68
+
54
g_free(name);
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)
55
}
78
}
56
}
79
}
57
+ if (info->has_cpuid) {
80
58
+ for (i = 0; i < info->num_cpus; i++) {
81
+ gicv3_add_its(s->gicv3, dev);
59
+ char *name = g_strdup_printf("cpuid%d", i);
60
+
82
+
61
+ sysbus_init_child_obj(obj, name, &s->cpuid[i],
83
gicv3_its_init_mmio(s, &gicv3_its_control_ops, &gicv3_its_translation_ops);
62
+ sizeof(s->cpuid[i]),
84
63
+ TYPE_ARMSSE_CPUID);
85
/* set the ITS default features supported */
64
+ g_free(name);
86
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
65
+ }
87
index XXXXXXX..XXXXXXX 100644
66
+ }
88
--- a/hw/intc/arm_gicv3_its_kvm.c
67
object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
89
+++ b/hw/intc/arm_gicv3_its_kvm.c
68
sizeof(s->nmi_orgate), TYPE_OR_IRQ,
90
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
69
&error_abort, NULL);
91
kvm_arm_register_device(&s->iomem_its_cntrl, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
70
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
92
KVM_VGIC_ITS_ADDR_TYPE, s->dev_fd, 0);
71
memory_region_add_subregion(&s->cpu_container[i], 0x50011000, mr);
93
72
}
94
+ gicv3_add_its(s->gicv3, dev);
73
}
74
+ if (info->has_cpuid) {
75
+ for (i = 0; i < info->num_cpus; i++) {
76
+ MemoryRegion *mr;
77
+
95
+
78
+ qdev_prop_set_uint32(DEVICE(&s->cpuid[i]), "CPUID", i);
96
gicv3_its_init_mmio(s, NULL, NULL);
79
+ object_property_set_bool(OBJECT(&s->cpuid[i]), true,
97
80
+ "realized", &err);
98
if (!kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
81
+ if (err) {
82
+ error_propagate(errp, err);
83
+ return;
84
+ }
85
+
86
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpuid[i]), 0);
87
+ memory_region_add_subregion(&s->cpu_container[i], 0x4001F000, mr);
88
+ }
89
+ }
90
91
/* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
92
/* Devices behind APB PPC1:
93
--
99
--
94
2.20.1
100
2.25.1
95
96
diff view generated by jsdifflib
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
Implement the GICv4 VMOVP command, which updates an entry in the vPE
2
table to change its rdbase field. This command is unique in the ITS
3
command set because its effects must be propagated to all the other
4
ITSes connected to the same GIC as the ITS which executes the VMOVP
5
command.
2
6
3
The nRF51 contains three regions of non-volatile memory (NVM):
7
The GICv4 spec allows two implementation choices for handling the
4
- CODE (R/W): contains code
8
propagation to other ITSes:
5
- FICR (R): Factory information like code size, chip id etc.
9
* If GITS_TYPER.VMOVP is 1, the guest only needs to issue the command
6
- UICR (R/W): Changeable configuration data. Lock bits, Code
10
on one ITS, and the implementation handles the propagation to
7
protection configuration, Bootloader address, Nordic SoftRadio
11
all ITSes
8
configuration, Firmware configuration.
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
9
16
10
Read and write access to the memories is managed by the
17
We choose the GITS_TYPER.VMOVP = 1 approach, and synchronously
11
Non-volatile memory controller.
18
execute the update on every ITS.
12
19
13
Memory schema:
20
For GICv4.1 this command has extra fields in the command packet and
14
[ CPU ] -+- [ NVM, either FICR, UICR or CODE ]
21
additional behaviour. We define the 4.1-only fields with the FIELD
15
| |
22
macro, but only implement the GICv4.0 version of the command.
16
\- [ NVMC ]
17
23
18
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
24
Note that we don't update the reported GITS_TYPER value here;
19
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
25
we'll do that later in a commit which updates all the reported
20
Tested-by: Joel Stanley <joel@jms.id.au>
26
feature bit and ID register values for GICv4.
21
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
27
22
Message-id: 20190201023357.22596-2-stefanha@redhat.com
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
30
Message-id: 20220408141550.1271295-17-peter.maydell@linaro.org
24
---
31
---
25
hw/nvram/Makefile.objs | 1 +
32
hw/intc/gicv3_internal.h | 18 ++++++++++
26
include/hw/nvram/nrf51_nvm.h | 64 ++++++
33
hw/intc/arm_gicv3_its.c | 75 ++++++++++++++++++++++++++++++++++++++++
27
hw/nvram/nrf51_nvm.c | 388 +++++++++++++++++++++++++++++++++++
34
hw/intc/trace-events | 1 +
28
3 files changed, 453 insertions(+)
35
3 files changed, 94 insertions(+)
29
create mode 100644 include/hw/nvram/nrf51_nvm.h
30
create mode 100644 hw/nvram/nrf51_nvm.c
31
36
32
diff --git a/hw/nvram/Makefile.objs b/hw/nvram/Makefile.objs
37
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
33
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/nvram/Makefile.objs
39
--- a/hw/intc/gicv3_internal.h
35
+++ b/hw/nvram/Makefile.objs
40
+++ b/hw/intc/gicv3_internal.h
36
@@ -XXX,XX +XXX,XX @@ common-obj-y += fw_cfg.o
41
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
37
common-obj-y += chrp_nvram.o
42
#define GITS_CMD_INVALL 0x0D
38
common-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o
43
#define GITS_CMD_MOVALL 0x0E
39
obj-$(CONFIG_PSERIES) += spapr_nvram.o
44
#define GITS_CMD_DISCARD 0x0F
40
+obj-$(CONFIG_NRF51_SOC) += nrf51_nvm.o
45
+#define GITS_CMD_VMOVP 0x22
41
diff --git a/include/hw/nvram/nrf51_nvm.h b/include/hw/nvram/nrf51_nvm.h
46
#define GITS_CMD_VMAPP 0x29
42
new file mode 100644
47
#define GITS_CMD_VMAPTI 0x2A
43
index XXXXXXX..XXXXXXX
48
#define GITS_CMD_VMAPI 0x2B
44
--- /dev/null
49
@@ -XXX,XX +XXX,XX @@ FIELD(VMAPP_2, V, 63, 1)
45
+++ b/include/hw/nvram/nrf51_nvm.h
50
FIELD(VMAPP_3, VPTSIZE, 0, 8) /* For GICv4.0, bits [7:6] are RES0 */
46
@@ -XXX,XX +XXX,XX @@
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
+
61
/*
62
* 12 bytes Interrupt translation Table Entry size
63
* as per Table 5.3 in GICv3 spec
64
@@ -XXX,XX +XXX,XX @@ static inline void gicv3_add_its(GICv3State *s, DeviceState *its)
65
g_ptr_array_add(s->itslist, its);
66
}
67
47
+/*
68
+/*
48
+ * Nordic Semiconductor nRF51 non-volatile memory
69
+ * The ITS can use this for operations that must be performed on
49
+ *
70
+ * every ITS connected to the same GIC that it is
50
+ * It provides an interface to erase regions in flash memory.
51
+ * Furthermore it provides the user and factory information registers.
52
+ *
53
+ * QEMU interface:
54
+ * + sysbus MMIO regions 0: NVMC peripheral registers
55
+ * + sysbus MMIO regions 1: FICR peripheral registers
56
+ * + sysbus MMIO regions 2: UICR peripheral registers
57
+ * + flash-size property: flash size in bytes.
58
+ *
59
+ * Accuracy of the peripheral model:
60
+ * + Code regions (MPU configuration) are disregarded.
61
+ *
62
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
63
+ *
64
+ * This code is licensed under the GPL version 2 or later. See
65
+ * the COPYING file in the top-level directory.
66
+ *
67
+ */
71
+ */
68
+#ifndef NRF51_NVM_H
72
+static inline void gicv3_foreach_its(GICv3State *s, GFunc func, void *opaque)
69
+#define NRF51_NVM_H
70
+
71
+#include "hw/sysbus.h"
72
+#define TYPE_NRF51_NVM "nrf51_soc.nvm"
73
+#define NRF51_NVM(obj) OBJECT_CHECK(NRF51NVMState, (obj), TYPE_NRF51_NVM)
74
+
75
+#define NRF51_UICR_FIXTURE_SIZE 64
76
+
77
+#define NRF51_NVMC_SIZE 0x1000
78
+
79
+#define NRF51_NVMC_READY 0x400
80
+#define NRF51_NVMC_READY_READY 0x01
81
+#define NRF51_NVMC_CONFIG 0x504
82
+#define NRF51_NVMC_CONFIG_MASK 0x03
83
+#define NRF51_NVMC_CONFIG_WEN 0x01
84
+#define NRF51_NVMC_CONFIG_EEN 0x02
85
+#define NRF51_NVMC_ERASEPCR1 0x508
86
+#define NRF51_NVMC_ERASEPCR0 0x510
87
+#define NRF51_NVMC_ERASEALL 0x50C
88
+#define NRF51_NVMC_ERASEUICR 0x514
89
+#define NRF51_NVMC_ERASE 0x01
90
+
91
+#define NRF51_UICR_SIZE 0x100
92
+
93
+typedef struct NRF51NVMState {
94
+ SysBusDevice parent_obj;
95
+
96
+ MemoryRegion mmio;
97
+ MemoryRegion ficr;
98
+ MemoryRegion uicr;
99
+ MemoryRegion flash;
100
+
101
+ uint32_t uicr_content[NRF51_UICR_FIXTURE_SIZE];
102
+ uint32_t flash_size;
103
+ uint8_t *storage;
104
+
105
+ uint32_t config;
106
+
107
+} NRF51NVMState;
108
+
109
+
110
+#endif
111
diff --git a/hw/nvram/nrf51_nvm.c b/hw/nvram/nrf51_nvm.c
112
new file mode 100644
113
index XXXXXXX..XXXXXXX
114
--- /dev/null
115
+++ b/hw/nvram/nrf51_nvm.c
116
@@ -XXX,XX +XXX,XX @@
117
+/*
118
+ * Nordic Semiconductor nRF51 non-volatile memory
119
+ *
120
+ * It provides an interface to erase regions in flash memory.
121
+ * Furthermore it provides the user and factory information registers.
122
+ *
123
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
124
+ *
125
+ * See nRF51 reference manual and product sheet sections:
126
+ * + Non-Volatile Memory Controller (NVMC)
127
+ * + Factory Information Configuration Registers (FICR)
128
+ * + User Information Configuration Registers (UICR)
129
+ *
130
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
131
+ *
132
+ * This code is licensed under the GPL version 2 or later. See
133
+ * the COPYING file in the top-level directory.
134
+ */
135
+
136
+#include "qemu/osdep.h"
137
+#include "qapi/error.h"
138
+#include "qemu/log.h"
139
+#include "exec/address-spaces.h"
140
+#include "hw/arm/nrf51.h"
141
+#include "hw/nvram/nrf51_nvm.h"
142
+
143
+/*
144
+ * FICR Registers Assignments
145
+ * CODEPAGESIZE 0x010
146
+ * CODESIZE 0x014
147
+ * CLENR0 0x028
148
+ * PPFC 0x02C
149
+ * NUMRAMBLOCK 0x034
150
+ * SIZERAMBLOCKS 0x038
151
+ * SIZERAMBLOCK[0] 0x038
152
+ * SIZERAMBLOCK[1] 0x03C
153
+ * SIZERAMBLOCK[2] 0x040
154
+ * SIZERAMBLOCK[3] 0x044
155
+ * CONFIGID 0x05C
156
+ * DEVICEID[0] 0x060
157
+ * DEVICEID[1] 0x064
158
+ * ER[0] 0x080
159
+ * ER[1] 0x084
160
+ * ER[2] 0x088
161
+ * ER[3] 0x08C
162
+ * IR[0] 0x090
163
+ * IR[1] 0x094
164
+ * IR[2] 0x098
165
+ * IR[3] 0x09C
166
+ * DEVICEADDRTYPE 0x0A0
167
+ * DEVICEADDR[0] 0x0A4
168
+ * DEVICEADDR[1] 0x0A8
169
+ * OVERRIDEEN 0x0AC
170
+ * NRF_1MBIT[0] 0x0B0
171
+ * NRF_1MBIT[1] 0x0B4
172
+ * NRF_1MBIT[2] 0x0B8
173
+ * NRF_1MBIT[3] 0x0BC
174
+ * NRF_1MBIT[4] 0x0C0
175
+ * BLE_1MBIT[0] 0x0EC
176
+ * BLE_1MBIT[1] 0x0F0
177
+ * BLE_1MBIT[2] 0x0F4
178
+ * BLE_1MBIT[3] 0x0F8
179
+ * BLE_1MBIT[4] 0x0FC
180
+ */
181
+static const uint32_t ficr_content[64] = {
182
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000400,
183
+ 0x00000100, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000002, 0x00002000,
184
+ 0x00002000, 0x00002000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
185
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
186
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000003,
187
+ 0x12345678, 0x9ABCDEF1, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
188
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
189
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
190
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
191
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
192
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
193
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
194
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
195
+};
196
+
197
+static uint64_t ficr_read(void *opaque, hwaddr offset, unsigned int size)
198
+{
73
+{
199
+ assert(offset < sizeof(ficr_content));
74
+ g_ptr_array_foreach(s->itslist, func, opaque);
200
+ return ficr_content[offset / 4];
201
+}
75
+}
202
+
76
+
203
+static void ficr_write(void *opaque, hwaddr offset, uint64_t value,
77
#endif /* QEMU_ARM_GICV3_INTERNAL_H */
204
+ unsigned int size)
78
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/hw/intc/arm_gicv3_its.c
81
+++ b/hw/intc/arm_gicv3_its.c
82
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_vmapp(GICv3ITSState *s, const uint64_t *cmdpkt)
83
return update_vte(s, vpeid, &vte) ? CMD_CONTINUE_OK : CMD_STALL;
84
}
85
86
+typedef struct VmovpCallbackData {
87
+ uint64_t rdbase;
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
+
96
+static void vmovp_callback(gpointer data, gpointer opaque)
205
+{
97
+{
206
+ /* Intentionally do nothing */
98
+ /*
207
+}
99
+ * This function is called to update the VPEID field in a VPE
100
+ * table entry for this ITS. This might be because of a VMOVP
101
+ * command executed on any ITS that is connected to the same GIC
102
+ * as this ITS. We need to read the VPE table entry for the VPEID
103
+ * and update its RDBASE field.
104
+ */
105
+ GICv3ITSState *s = data;
106
+ VmovpCallbackData *cbdata = opaque;
107
+ VTEntry vte;
108
+ ItsCmdResult cmdres;
208
+
109
+
209
+static const MemoryRegionOps ficr_ops = {
110
+ cmdres = lookup_vte(s, __func__, cbdata->vpeid, &vte);
210
+ .read = ficr_read,
111
+ switch (cmdres) {
211
+ .write = ficr_write,
112
+ case CMD_STALL:
212
+ .impl.min_access_size = 4,
113
+ cbdata->result = CMD_STALL;
213
+ .impl.max_access_size = 4,
114
+ return;
214
+ .endianness = DEVICE_LITTLE_ENDIAN
115
+ case CMD_CONTINUE:
215
+};
116
+ if (cbdata->result != CMD_STALL) {
216
+
117
+ cbdata->result = CMD_CONTINUE;
217
+/*
118
+ }
218
+ * UICR Registers Assignments
119
+ return;
219
+ * CLENR0 0x000
120
+ case CMD_CONTINUE_OK:
220
+ * RBPCONF 0x004
221
+ * XTALFREQ 0x008
222
+ * FWID 0x010
223
+ * BOOTLOADERADDR 0x014
224
+ * NRFFW[0] 0x014
225
+ * NRFFW[1] 0x018
226
+ * NRFFW[2] 0x01C
227
+ * NRFFW[3] 0x020
228
+ * NRFFW[4] 0x024
229
+ * NRFFW[5] 0x028
230
+ * NRFFW[6] 0x02C
231
+ * NRFFW[7] 0x030
232
+ * NRFFW[8] 0x034
233
+ * NRFFW[9] 0x038
234
+ * NRFFW[10] 0x03C
235
+ * NRFFW[11] 0x040
236
+ * NRFFW[12] 0x044
237
+ * NRFFW[13] 0x048
238
+ * NRFFW[14] 0x04C
239
+ * NRFHW[0] 0x050
240
+ * NRFHW[1] 0x054
241
+ * NRFHW[2] 0x058
242
+ * NRFHW[3] 0x05C
243
+ * NRFHW[4] 0x060
244
+ * NRFHW[5] 0x064
245
+ * NRFHW[6] 0x068
246
+ * NRFHW[7] 0x06C
247
+ * NRFHW[8] 0x070
248
+ * NRFHW[9] 0x074
249
+ * NRFHW[10] 0x078
250
+ * NRFHW[11] 0x07C
251
+ * CUSTOMER[0] 0x080
252
+ * CUSTOMER[1] 0x084
253
+ * CUSTOMER[2] 0x088
254
+ * CUSTOMER[3] 0x08C
255
+ * CUSTOMER[4] 0x090
256
+ * CUSTOMER[5] 0x094
257
+ * CUSTOMER[6] 0x098
258
+ * CUSTOMER[7] 0x09C
259
+ * CUSTOMER[8] 0x0A0
260
+ * CUSTOMER[9] 0x0A4
261
+ * CUSTOMER[10] 0x0A8
262
+ * CUSTOMER[11] 0x0AC
263
+ * CUSTOMER[12] 0x0B0
264
+ * CUSTOMER[13] 0x0B4
265
+ * CUSTOMER[14] 0x0B8
266
+ * CUSTOMER[15] 0x0BC
267
+ * CUSTOMER[16] 0x0C0
268
+ * CUSTOMER[17] 0x0C4
269
+ * CUSTOMER[18] 0x0C8
270
+ * CUSTOMER[19] 0x0CC
271
+ * CUSTOMER[20] 0x0D0
272
+ * CUSTOMER[21] 0x0D4
273
+ * CUSTOMER[22] 0x0D8
274
+ * CUSTOMER[23] 0x0DC
275
+ * CUSTOMER[24] 0x0E0
276
+ * CUSTOMER[25] 0x0E4
277
+ * CUSTOMER[26] 0x0E8
278
+ * CUSTOMER[27] 0x0EC
279
+ * CUSTOMER[28] 0x0F0
280
+ * CUSTOMER[29] 0x0F4
281
+ * CUSTOMER[30] 0x0F8
282
+ * CUSTOMER[31] 0x0FC
283
+ */
284
+
285
+static uint64_t uicr_read(void *opaque, hwaddr offset, unsigned int size)
286
+{
287
+ NRF51NVMState *s = NRF51_NVM(opaque);
288
+
289
+ assert(offset < sizeof(s->uicr_content));
290
+ return s->uicr_content[offset / 4];
291
+}
292
+
293
+static void uicr_write(void *opaque, hwaddr offset, uint64_t value,
294
+ unsigned int size)
295
+{
296
+ NRF51NVMState *s = NRF51_NVM(opaque);
297
+
298
+ assert(offset < sizeof(s->uicr_content));
299
+ s->uicr_content[offset / 4] = value;
300
+}
301
+
302
+static const MemoryRegionOps uicr_ops = {
303
+ .read = uicr_read,
304
+ .write = uicr_write,
305
+ .impl.min_access_size = 4,
306
+ .impl.max_access_size = 4,
307
+ .endianness = DEVICE_LITTLE_ENDIAN
308
+};
309
+
310
+
311
+static uint64_t io_read(void *opaque, hwaddr offset, unsigned int size)
312
+{
313
+ NRF51NVMState *s = NRF51_NVM(opaque);
314
+ uint64_t r = 0;
315
+
316
+ switch (offset) {
317
+ case NRF51_NVMC_READY:
318
+ r = NRF51_NVMC_READY_READY;
319
+ break;
320
+ case NRF51_NVMC_CONFIG:
321
+ r = s->config;
322
+ break;
323
+ default:
324
+ qemu_log_mask(LOG_GUEST_ERROR,
325
+ "%s: bad read offset 0x%" HWADDR_PRIx "\n", __func__, offset);
326
+ break;
121
+ break;
327
+ }
122
+ }
328
+
123
+
329
+ return r;
124
+ vte.rdbase = cbdata->rdbase;
330
+}
125
+ if (!update_vte(s, cbdata->vpeid, &vte)) {
331
+
126
+ cbdata->result = CMD_STALL;
332
+static void io_write(void *opaque, hwaddr offset, uint64_t value,
333
+ unsigned int size)
334
+{
335
+ NRF51NVMState *s = NRF51_NVM(opaque);
336
+
337
+ switch (offset) {
338
+ case NRF51_NVMC_CONFIG:
339
+ s->config = value & NRF51_NVMC_CONFIG_MASK;
340
+ break;
341
+ case NRF51_NVMC_ERASEPCR0:
342
+ case NRF51_NVMC_ERASEPCR1:
343
+ if (s->config & NRF51_NVMC_CONFIG_EEN) {
344
+ /* Mask in-page sub address */
345
+ value &= ~(NRF51_PAGE_SIZE - 1);
346
+ if (value <= (s->flash_size - NRF51_PAGE_SIZE)) {
347
+ memset(s->storage + value, 0xFF, NRF51_PAGE_SIZE);
348
+ memory_region_flush_rom_device(&s->flash, value,
349
+ NRF51_PAGE_SIZE);
350
+ }
351
+ } else {
352
+ qemu_log_mask(LOG_GUEST_ERROR,
353
+ "%s: Flash erase at 0x%" HWADDR_PRIx" while flash not erasable.\n",
354
+ __func__, offset);
355
+ }
356
+ break;
357
+ case NRF51_NVMC_ERASEALL:
358
+ if (value == NRF51_NVMC_ERASE) {
359
+ if (s->config & NRF51_NVMC_CONFIG_EEN) {
360
+ memset(s->storage, 0xFF, s->flash_size);
361
+ memory_region_flush_rom_device(&s->flash, 0, s->flash_size);
362
+ memset(s->uicr_content, 0xFF, sizeof(s->uicr_content));
363
+ } else {
364
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Flash not erasable.\n",
365
+ __func__);
366
+ }
367
+ }
368
+ break;
369
+ case NRF51_NVMC_ERASEUICR:
370
+ if (value == NRF51_NVMC_ERASE) {
371
+ memset(s->uicr_content, 0xFF, sizeof(s->uicr_content));
372
+ }
373
+ break;
374
+
375
+ default:
376
+ qemu_log_mask(LOG_GUEST_ERROR,
377
+ "%s: bad write offset 0x%" HWADDR_PRIx "\n", __func__, offset);
378
+ }
127
+ }
379
+}
128
+}
380
+
129
+
381
+static const MemoryRegionOps io_ops = {
130
+static ItsCmdResult process_vmovp(GICv3ITSState *s, const uint64_t *cmdpkt)
382
+ .read = io_read,
131
+{
383
+ .write = io_write,
132
+ VmovpCallbackData cbdata;
384
+ .impl.min_access_size = 4,
385
+ .impl.max_access_size = 4,
386
+ .endianness = DEVICE_LITTLE_ENDIAN,
387
+};
388
+
133
+
134
+ if (!its_feature_virtual(s)) {
135
+ return CMD_CONTINUE;
136
+ }
389
+
137
+
390
+static void flash_write(void *opaque, hwaddr offset, uint64_t value,
138
+ cbdata.vpeid = FIELD_EX64(cmdpkt[1], VMOVP_1, VPEID);
391
+ unsigned int size)
139
+ cbdata.rdbase = FIELD_EX64(cmdpkt[2], VMOVP_2, RDBASE);
392
+{
393
+ NRF51NVMState *s = NRF51_NVM(opaque);
394
+
140
+
395
+ if (s->config & NRF51_NVMC_CONFIG_WEN) {
141
+ trace_gicv3_its_cmd_vmovp(cbdata.vpeid, cbdata.rdbase);
396
+ uint32_t oldval;
397
+
142
+
398
+ assert(offset + size <= s->flash_size);
143
+ if (cbdata.rdbase >= s->gicv3->num_cpu) {
144
+ return CMD_CONTINUE;
145
+ }
399
+
146
+
400
+ /* NOR Flash only allows bits to be flipped from 1's to 0's on write */
147
+ /*
401
+ oldval = ldl_le_p(s->storage + offset);
148
+ * Our ITS implementation reports GITS_TYPER.VMOVP == 1, which means
402
+ oldval &= value;
149
+ * that when the VMOVP command is executed on an ITS to change the
403
+ stl_le_p(s->storage + offset, oldval);
150
+ * VPEID field in a VPE table entry the change must be propagated
404
+
151
+ * to all the ITSes connected to the same GIC.
405
+ memory_region_flush_rom_device(&s->flash, offset, size);
152
+ */
406
+ } else {
153
+ cbdata.result = CMD_CONTINUE_OK;
407
+ qemu_log_mask(LOG_GUEST_ERROR,
154
+ gicv3_foreach_its(s->gicv3, vmovp_callback, &cbdata);
408
+ "%s: Flash write 0x%" HWADDR_PRIx" while flash not writable.\n",
155
+ return cbdata.result;
409
+ __func__, offset);
410
+ }
411
+}
156
+}
412
+
157
+
413
+
158
/*
414
+
159
* Current implementation blocks until all
415
+static const MemoryRegionOps flash_ops = {
160
* commands are processed
416
+ .write = flash_write,
161
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
417
+ .valid.min_access_size = 4,
162
case GITS_CMD_VMAPP:
418
+ .valid.max_access_size = 4,
163
result = process_vmapp(s, cmdpkt);
419
+ .endianness = DEVICE_LITTLE_ENDIAN,
164
break;
420
+};
165
+ case GITS_CMD_VMOVP:
421
+
166
+ result = process_vmovp(s, cmdpkt);
422
+static void nrf51_nvm_init(Object *obj)
167
+ break;
423
+{
168
default:
424
+ NRF51NVMState *s = NRF51_NVM(obj);
169
trace_gicv3_its_cmd_unknown(cmd);
425
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
170
break;
426
+
171
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
427
+ memory_region_init_io(&s->mmio, obj, &io_ops, s, "nrf51_soc.nvmc",
172
index XXXXXXX..XXXXXXX 100644
428
+ NRF51_NVMC_SIZE);
173
--- a/hw/intc/trace-events
429
+ sysbus_init_mmio(sbd, &s->mmio);
174
+++ b/hw/intc/trace-events
430
+
175
@@ -XXX,XX +XXX,XX @@ gicv3_its_cmd_movi(uint32_t devid, uint32_t eventid, uint32_t icid) "GICv3 ITS:
431
+ memory_region_init_io(&s->ficr, obj, &ficr_ops, s, "nrf51_soc.ficr",
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"
432
+ sizeof(ficr_content));
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"
433
+ sysbus_init_mmio(sbd, &s->ficr);
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"
434
+
179
+gicv3_its_cmd_vmovp(uint32_t vpeid, uint64_t rdbase) "GICv3 ITS: command VMOVP vPEID 0x%x RDbase 0x%" PRIx64
435
+ memory_region_init_io(&s->uicr, obj, &uicr_ops, s, "nrf51_soc.uicr",
180
gicv3_its_cmd_unknown(unsigned cmd) "GICv3 ITS: unknown command 0x%x"
436
+ sizeof(s->uicr_content));
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"
437
+ sysbus_init_mmio(sbd, &s->uicr);
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"
438
+}
439
+
440
+static void nrf51_nvm_realize(DeviceState *dev, Error **errp)
441
+{
442
+ NRF51NVMState *s = NRF51_NVM(dev);
443
+ Error *err = NULL;
444
+
445
+ memory_region_init_rom_device(&s->flash, OBJECT(dev), &flash_ops, s,
446
+ "nrf51_soc.flash", s->flash_size, &err);
447
+ if (err) {
448
+ error_propagate(errp, err);
449
+ return;
450
+ }
451
+
452
+ s->storage = memory_region_get_ram_ptr(&s->flash);
453
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->flash);
454
+}
455
+
456
+static void nrf51_nvm_reset(DeviceState *dev)
457
+{
458
+ NRF51NVMState *s = NRF51_NVM(dev);
459
+
460
+ s->config = 0x00;
461
+ memset(s->uicr_content, 0xFF, sizeof(s->uicr_content));
462
+}
463
+
464
+static Property nrf51_nvm_properties[] = {
465
+ DEFINE_PROP_UINT32("flash-size", NRF51NVMState, flash_size, 0x40000),
466
+ DEFINE_PROP_END_OF_LIST(),
467
+};
468
+
469
+static const VMStateDescription vmstate_nvm = {
470
+ .name = "nrf51_soc.nvm",
471
+ .version_id = 1,
472
+ .minimum_version_id = 1,
473
+ .fields = (VMStateField[]) {
474
+ VMSTATE_UINT32_ARRAY(uicr_content, NRF51NVMState,
475
+ NRF51_UICR_FIXTURE_SIZE),
476
+ VMSTATE_UINT32(config, NRF51NVMState),
477
+ VMSTATE_END_OF_LIST()
478
+ }
479
+};
480
+
481
+static void nrf51_nvm_class_init(ObjectClass *klass, void *data)
482
+{
483
+ DeviceClass *dc = DEVICE_CLASS(klass);
484
+
485
+ dc->props = nrf51_nvm_properties;
486
+ dc->vmsd = &vmstate_nvm;
487
+ dc->realize = nrf51_nvm_realize;
488
+ dc->reset = nrf51_nvm_reset;
489
+}
490
+
491
+static const TypeInfo nrf51_nvm_info = {
492
+ .name = TYPE_NRF51_NVM,
493
+ .parent = TYPE_SYS_BUS_DEVICE,
494
+ .instance_size = sizeof(NRF51NVMState),
495
+ .instance_init = nrf51_nvm_init,
496
+ .class_init = nrf51_nvm_class_init
497
+};
498
+
499
+static void nrf51_nvm_register_types(void)
500
+{
501
+ type_register_static(&nrf51_nvm_info);
502
+}
503
+
504
+type_init(nrf51_nvm_register_types)
505
--
183
--
506
2.20.1
184
2.25.1
507
508
diff view generated by jsdifflib
New 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.
1
5
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
1
In preparation for adding support for the AN521 MPS2 image, we need
1
We were previously implementing INV (like INVALL) to just blow away
2
to handle wiring up the MPS2 device interrupt lines to both CPUs in
2
cached highest-priority-pending-LPI information on all connected
3
the SSE-200, rather than just the one that the IoTKit has.
3
redistributors. For GICv4.0, this isn't going to be sufficient,
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.
4
9
5
Abstract out a "connect to the IoTKit interrupt line" function
10
Split out INV handling into a process_inv() function like our other
6
and make it connect to a splitter which feeds both sets of inputs
11
command-processing functions. For the moment, stick to handling only
7
for the SSE-200 case.
12
physical LPIs; we will add the vLPI parts later.
8
13
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20190121185118.18550-23-peter.maydell@linaro.org
16
Message-id: 20220408141550.1271295-19-peter.maydell@linaro.org
12
---
17
---
13
hw/arm/mps2-tz.c | 79 ++++++++++++++++++++++++++++++++++++------------
18
hw/intc/gicv3_internal.h | 12 +++++++++
14
1 file changed, 59 insertions(+), 20 deletions(-)
19
hw/intc/arm_gicv3_its.c | 50 +++++++++++++++++++++++++++++++++++++-
20
hw/intc/arm_gicv3_redist.c | 11 +++++++++
21
hw/intc/trace-events | 3 ++-
22
4 files changed, 74 insertions(+), 2 deletions(-)
15
23
16
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
24
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
17
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/mps2-tz.c
26
--- a/hw/intc/gicv3_internal.h
19
+++ b/hw/arm/mps2-tz.c
27
+++ b/hw/intc/gicv3_internal.h
20
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@ FIELD(MOVI_0, DEVICEID, 32, 32)
21
#include "net/net.h"
29
FIELD(MOVI_1, EVENTID, 0, 32)
22
#include "hw/core/split-irq.h"
30
FIELD(MOVI_2, ICID, 0, 16)
23
31
24
+#define MPS2TZ_NUMIRQ 92
32
+/* INV command fields */
33
+FIELD(INV_0, DEVICEID, 32, 32)
34
+FIELD(INV_1, EVENTID, 0, 32)
25
+
35
+
26
typedef enum MPS2TZFPGAType {
36
/* VMAPI, VMAPTI command fields */
27
FPGA_AN505,
37
FIELD(VMAPTI_0, DEVICEID, 32, 32)
28
+ FPGA_AN521,
38
FIELD(VMAPTI_1, EVENTID, 0, 32)
29
} MPS2TZFPGAType;
39
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_update_lpi(GICv3CPUState *cs);
30
40
* an incoming migration has loaded new state.
31
typedef struct {
41
*/
32
@@ -XXX,XX +XXX,XX @@ typedef struct {
42
void gicv3_redist_update_lpi_only(GICv3CPUState *cs);
33
SplitIRQ sec_resp_splitter;
43
+/**
34
qemu_or_irq uart_irq_orgate;
44
+ * gicv3_redist_inv_lpi:
35
DeviceState *lan9118;
45
+ * @cs: GICv3CPUState
36
+ SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ];
46
+ * @irq: LPI to invalidate cached information for
37
} MPS2TZMachineState;
47
+ *
38
48
+ * Forget or update any cached information associated with this LPI.
39
#define TYPE_MPS2TZ_MACHINE "mps2tz"
49
+ */
40
@@ -XXX,XX +XXX,XX @@ static void make_ram_alias(MemoryRegion *mr, const char *name,
50
+void gicv3_redist_inv_lpi(GICv3CPUState *cs, int irq);
41
memory_region_add_subregion(get_system_memory(), base, mr);
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
56
--- a/hw/intc/arm_gicv3_its.c
57
+++ b/hw/intc/arm_gicv3_its.c
58
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_vmovp(GICv3ITSState *s, const uint64_t *cmdpkt)
59
return cbdata.result;
42
}
60
}
43
61
44
+static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
62
+static ItsCmdResult process_inv(GICv3ITSState *s, const uint64_t *cmdpkt)
45
+{
63
+{
46
+ /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
64
+ uint32_t devid, eventid;
47
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
65
+ ITEntry ite;
66
+ DTEntry dte;
67
+ CTEntry cte;
68
+ ItsCmdResult cmdres;
48
+
69
+
49
+ assert(irqno < MPS2TZ_NUMIRQ);
70
+ devid = FIELD_EX64(cmdpkt[0], INV_0, DEVICEID);
71
+ eventid = FIELD_EX64(cmdpkt[1], INV_1, EVENTID);
50
+
72
+
51
+ switch (mmc->fpga_type) {
73
+ trace_gicv3_its_cmd_inv(devid, eventid);
52
+ case FPGA_AN505:
74
+
53
+ return qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "EXP_IRQ", irqno);
75
+ cmdres = lookup_ite(s, __func__, devid, eventid, &ite, &dte);
54
+ case FPGA_AN521:
76
+ if (cmdres != CMD_CONTINUE_OK) {
55
+ return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
77
+ return cmdres;
78
+ }
79
+
80
+ switch (ite.inttype) {
81
+ case ITE_INTTYPE_PHYSICAL:
82
+ cmdres = lookup_cte(s, __func__, ite.icid, &cte);
83
+ if (cmdres != CMD_CONTINUE_OK) {
84
+ return cmdres;
85
+ }
86
+ gicv3_redist_inv_lpi(&s->gicv3->cpu[cte.rdbase], ite.intid);
87
+ break;
88
+ case ITE_INTTYPE_VIRTUAL:
89
+ if (!its_feature_virtual(s)) {
90
+ /* Can't happen unless guest is illegally writing to table memory */
91
+ qemu_log_mask(LOG_GUEST_ERROR,
92
+ "%s: invalid type %d in ITE (table corrupted?)\n",
93
+ __func__, ite.inttype);
94
+ return CMD_CONTINUE;
95
+ }
96
+ /* We will implement the vLPI invalidation in a later commit */
97
+ g_assert_not_reached();
98
+ break;
56
+ default:
99
+ default:
57
+ g_assert_not_reached();
100
+ g_assert_not_reached();
58
+ }
101
+ }
102
+
103
+ return CMD_CONTINUE_OK;
59
+}
104
+}
60
+
105
+
61
/* Most of the devices in the AN505 FPGA image sit behind
106
/*
62
* Peripheral Protection Controllers. These data structures
107
* Current implementation blocks until all
63
* define the layout of which devices sit behind which PPCs.
108
* commands are processed
64
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
109
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
65
int txirqno = i * 2 + 1;
110
result = process_its_cmd(s, cmdpkt, DISCARD);
66
int combirqno = i + 10;
111
break;
67
SysBusDevice *s;
112
case GITS_CMD_INV:
68
- DeviceState *iotkitdev = DEVICE(&mms->iotkit);
113
+ result = process_inv(s, cmdpkt);
69
DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
114
+ break;
70
115
case GITS_CMD_INVALL:
71
sysbus_init_child_obj(OBJECT(mms), name, uart, sizeof(mms->uart[0]),
116
/*
72
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
117
* Current implementation doesn't cache any ITS tables,
73
qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ);
118
* but the calculated lpi priority information. We only
74
object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal);
119
* need to trigger lpi priority re-calculation to be in
75
s = SYS_BUS_DEVICE(uart);
120
* sync with LPI config table or pending table changes.
76
- sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev,
121
+ * INVALL operates on a collection specified by ICID so
77
- "EXP_IRQ", txirqno));
122
+ * it only affects physical LPIs.
78
- sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev,
123
*/
79
- "EXP_IRQ", rxirqno));
124
- trace_gicv3_its_cmd_inv();
80
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, txirqno));
125
+ trace_gicv3_its_cmd_invall();
81
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, rxirqno));
126
for (i = 0; i < s->gicv3->num_cpu; i++) {
82
sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2));
127
gicv3_redist_update_lpi(&s->gicv3->cpu[i]);
83
sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1));
128
}
84
- sysbus_connect_irq(s, 4, qdev_get_gpio_in_named(iotkitdev,
129
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
85
- "EXP_IRQ", combirqno));
130
index XXXXXXX..XXXXXXX 100644
86
+ sysbus_connect_irq(s, 4, get_sse_irq_in(mms, combirqno));
131
--- a/hw/intc/arm_gicv3_redist.c
87
return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
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);
88
}
135
}
89
136
90
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
137
+void gicv3_redist_inv_lpi(GICv3CPUState *cs, int irq)
91
const char *name, hwaddr size)
138
+{
139
+ /*
140
+ * The only cached information for LPIs we have is the HPPLPI.
141
+ * We could be cleverer about identifying when we don't need
142
+ * to do a full rescan of the pending table, but until we find
143
+ * this is a performance issue, just always recalculate.
144
+ */
145
+ gicv3_redist_update_lpi(cs);
146
+}
147
+
148
void gicv3_redist_mov_lpi(GICv3CPUState *src, GICv3CPUState *dest, int irq)
92
{
149
{
93
SysBusDevice *s;
150
/*
94
- DeviceState *iotkitdev = DEVICE(&mms->iotkit);
151
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
95
NICInfo *nd = &nd_table[0];
152
index XXXXXXX..XXXXXXX 100644
96
153
--- a/hw/intc/trace-events
97
/* In hardware this is a LAN9220; the LAN9118 is software compatible
154
+++ b/hw/intc/trace-events
98
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
155
@@ -XXX,XX +XXX,XX @@ gicv3_its_cmd_mapd(uint32_t devid, uint32_t size, uint64_t ittaddr, int valid) "
99
qdev_init_nofail(mms->lan9118);
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"
100
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"
101
s = SYS_BUS_DEVICE(mms->lan9118);
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"
102
- sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 16));
159
-gicv3_its_cmd_inv(void) "GICv3 ITS: command INV or INVALL"
103
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 16));
160
+gicv3_its_cmd_inv(uint32_t devid, uint32_t eventid) "GICv3 ITS: command INV DeviceID 0x%x EventID 0x%x"
104
return sysbus_mmio_get_region(s, 0);
161
+gicv3_its_cmd_invall(void) "GICv3 ITS: command INVALL"
105
}
162
gicv3_its_cmd_movall(uint64_t rd1, uint64_t rd2) "GICv3 ITS: command MOVALL RDbase1 0x%" PRIx64 " RDbase2 0x%" PRIx64
106
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"
107
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
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"
108
109
s = SYS_BUS_DEVICE(dma);
110
/* Wire up DMACINTR, DMACINTERR, DMACINTTC */
111
- sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev,
112
- "EXP_IRQ", 58 + i * 3));
113
- sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev,
114
- "EXP_IRQ", 56 + i * 3));
115
- sysbus_connect_irq(s, 2, qdev_get_gpio_in_named(iotkitdev,
116
- "EXP_IRQ", 57 + i * 3));
117
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 58 + i * 3));
118
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, 56 + i * 3));
119
+ sysbus_connect_irq(s, 2, get_sse_irq_in(mms, 57 + i * 3));
120
121
g_free(mscname);
122
return sysbus_mmio_get_region(s, 0);
123
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
124
*/
125
PL022State *spi = opaque;
126
int i = spi - &mms->spi[0];
127
- DeviceState *iotkitdev = DEVICE(&mms->iotkit);
128
SysBusDevice *s;
129
130
sysbus_init_child_obj(OBJECT(mms), name, spi, sizeof(mms->spi[0]),
131
TYPE_PL022);
132
object_property_set_bool(OBJECT(spi), true, "realized", &error_fatal);
133
s = SYS_BUS_DEVICE(spi);
134
- sysbus_connect_irq(s, 0,
135
- qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 51 + i));
136
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 51 + i));
137
return sysbus_mmio_get_region(s, 0);
138
}
139
140
static void mps2tz_common_init(MachineState *machine)
141
{
142
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
143
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
144
MachineClass *mc = MACHINE_GET_CLASS(machine);
145
MemoryRegion *system_memory = get_system_memory();
146
DeviceState *iotkitdev;
147
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
148
iotkitdev = DEVICE(&mms->iotkit);
149
object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory),
150
"memory", &error_abort);
151
- qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", 92);
152
+ qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
153
qdev_prop_set_uint32(iotkitdev, "MAINCLK", SYSCLK_FRQ);
154
object_property_set_bool(OBJECT(&mms->iotkit), true, "realized",
155
&error_fatal);
156
157
+ /*
158
+ * The AN521 needs us to create splitters to feed the IRQ inputs
159
+ * for each CPU in the SSE-200 from each device in the board.
160
+ */
161
+ if (mmc->fpga_type == FPGA_AN521) {
162
+ for (i = 0; i < MPS2TZ_NUMIRQ; i++) {
163
+ char *name = g_strdup_printf("mps2-irq-splitter%d", i);
164
+ SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
165
+
166
+ object_initialize_child(OBJECT(machine), name,
167
+ splitter, sizeof(*splitter),
168
+ TYPE_SPLIT_IRQ, &error_fatal, NULL);
169
+ g_free(name);
170
+
171
+ object_property_set_int(OBJECT(splitter), 2, "num-lines",
172
+ &error_fatal);
173
+ object_property_set_bool(OBJECT(splitter), true, "realized",
174
+ &error_fatal);
175
+ qdev_connect_gpio_out(DEVICE(splitter), 0,
176
+ qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
177
+ "EXP_IRQ", i));
178
+ qdev_connect_gpio_out(DEVICE(splitter), 1,
179
+ qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
180
+ "EXP_CPU1_IRQ", i));
181
+ }
182
+ }
183
+
184
/* The sec_resp_cfg output from the IoTKit must be split into multiple
185
* lines, one for each of the PPCs we create here, plus one per MSC.
186
*/
187
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
188
object_property_set_bool(OBJECT(&mms->uart_irq_orgate), true,
189
"realized", &error_fatal);
190
qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
191
- qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 15));
192
+ get_sse_irq_in(mms, 15));
193
194
/* Most of the devices in the FPGA are behind Peripheral Protection
195
* Controllers. The required order for initializing things is:
196
--
165
--
197
2.20.1
166
2.25.1
198
199
diff view generated by jsdifflib
New 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.
1
4
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
1
The SSE-200 has two Cortex-M33 CPUs. These see the same view
1
Implement the GICv4 VMOVI command, which moves the pending state
2
of memory, with the exception of the "private CPU region" which
2
of a virtual interrupt from one redistributor to another. As with
3
has per-CPU devices. Internal device interrupts for SSE-200
3
MOVI, we handle the "parse and validate command arguments and
4
devices are mostly wired up to both CPUs, with the exception of
4
table lookups" part in the ITS source file, and pass the final
5
a few per-CPU devices. External GPIO inputs on the SSE-200
5
results to a function in the redistributor which will do the
6
device are provided for the second CPU's interrupts above 32,
6
actual operation. As with the "make a VLPI pending" change,
7
as is already the case for the first CPU.
7
for the moment we leave that redistributor function as a stub,
8
8
to be implemented in a later commit.
9
Refactor the code to support creation of multiple CPUs.
10
For the moment we leave all CPUs with the same view of
11
memory: this will not work in the multiple-CPU case, but
12
we will fix this in the following commit.
13
9
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20190121185118.18550-12-peter.maydell@linaro.org
12
Message-id: 20220408141550.1271295-21-peter.maydell@linaro.org
17
---
13
---
18
include/hw/arm/armsse.h | 21 +++-
14
hw/intc/gicv3_internal.h | 23 +++++++++++
19
hw/arm/armsse.c | 206 ++++++++++++++++++++++++++++++++--------
15
hw/intc/arm_gicv3_its.c | 82 ++++++++++++++++++++++++++++++++++++++
20
2 files changed, 180 insertions(+), 47 deletions(-)
16
hw/intc/arm_gicv3_redist.c | 10 +++++
17
hw/intc/trace-events | 1 +
18
4 files changed, 116 insertions(+)
21
19
22
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
20
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
23
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/arm/armsse.h
22
--- a/hw/intc/gicv3_internal.h
25
+++ b/include/hw/arm/armsse.h
23
+++ b/hw/intc/gicv3_internal.h
26
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
27
* + QOM property "memory" is a MemoryRegion containing the devices provided
25
#define GITS_CMD_INVALL 0x0D
28
* by the board model.
26
#define GITS_CMD_MOVALL 0x0E
29
* + QOM property "MAINCLK" is the frequency of the main system clock
27
#define GITS_CMD_DISCARD 0x0F
30
- * + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts
28
+#define GITS_CMD_VMOVI 0x21
31
- * + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts, which
29
#define GITS_CMD_VMOVP 0x22
32
- * are wired to the NVIC lines 32 .. n+32
30
#define GITS_CMD_VSYNC 0x25
33
+ * + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts.
31
#define GITS_CMD_VMAPP 0x29
34
+ * (In hardware, the SSE-200 permits the number of expansion interrupts
32
@@ -XXX,XX +XXX,XX @@ FIELD(VMOVP_2, RDBASE, 16, 36)
35
+ * for the two CPUs to be configured separately, but we restrict it to
33
FIELD(VMOVP_2, DB, 63, 1) /* GICv4.1 only */
36
+ * being the same for both, to avoid having to have separate Property
34
FIELD(VMOVP_3, DEFAULT_DOORBELL, 0, 32) /* GICv4.1 only */
37
+ * lists for different variants. This restriction can be relaxed later
35
38
+ * if necessary.)
36
+/* VMOVI command fields */
39
+ * + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts for CPU 0,
37
+FIELD(VMOVI_0, DEVICEID, 32, 32)
40
+ * which are wired to its NVIC lines 32 .. n+32
38
+FIELD(VMOVI_1, EVENTID, 0, 32)
41
+ * + Named GPIO inputs "EXP_CPU1_IRQ" 0..n are the expansion interrupts for
39
+FIELD(VMOVI_1, VPEID, 32, 16)
42
+ * CPU 1, which are wired to its NVIC lines 32 .. n+32
40
+FIELD(VMOVI_2, D, 0, 1)
43
* + sysbus MMIO region 0 is the "AHB Slave Expansion" which allows
41
+FIELD(VMOVI_2, DOORBELL, 32, 32)
44
* bus master devices in the board model to make transactions into
42
+
45
* all the devices and memory areas in the IoTKit
43
/*
46
@@ -XXX,XX +XXX,XX @@
44
* 12 bytes Interrupt translation Table Entry size
47
#error Too many SRAM banks
45
* as per Table 5.3 in GICv3 spec
48
#endif
46
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_mov_lpi(GICv3CPUState *src, GICv3CPUState *dest, int irq);
49
47
* by the ITS MOVALL command.
50
+#define SSE_MAX_CPUS 2
51
+
52
typedef struct ARMSSE {
53
/*< private >*/
54
SysBusDevice parent_obj;
55
56
/*< public >*/
57
- ARMv7MState armv7m;
58
+ ARMv7MState armv7m[SSE_MAX_CPUS];
59
IoTKitSecCtl secctl;
60
TZPPC apb_ppc0;
61
TZPPC apb_ppc1;
62
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
63
qemu_or_irq mpc_irq_orgate;
64
qemu_or_irq nmi_orgate;
65
66
+ SplitIRQ cpu_irq_splitter[32];
67
+
68
CMSDKAPBDualTimer dualtimer;
69
70
CMSDKAPBWatchdog s32kwatchdog;
71
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
72
MemoryRegion alias3;
73
MemoryRegion sram[MAX_SRAM_BANKS];
74
75
- qemu_irq *exp_irqs;
76
+ qemu_irq *exp_irqs[SSE_MAX_CPUS];
77
qemu_irq ppc0_irq;
78
qemu_irq ppc1_irq;
79
qemu_irq sec_resp_cfg;
80
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/hw/arm/armsse.c
83
+++ b/hw/arm/armsse.c
84
@@ -XXX,XX +XXX,XX @@
85
struct ARMSSEInfo {
86
const char *name;
87
int sram_banks;
88
+ int num_cpus;
89
};
90
91
static const ARMSSEInfo armsse_variants[] = {
92
{
93
.name = TYPE_IOTKIT,
94
.sram_banks = 1,
95
+ .num_cpus = 1,
96
},
97
};
98
99
/* Clock frequency in HZ of the 32KHz "slow clock" */
100
#define S32KCLK (32 * 1000)
101
102
+/* Is internal IRQ n shared between CPUs in a multi-core SSE ? */
103
+static bool irq_is_common[32] = {
104
+ [0 ... 5] = true,
105
+ /* 6, 7: per-CPU MHU interrupts */
106
+ [8 ... 12] = true,
107
+ /* 13: per-CPU icache interrupt */
108
+ /* 14: reserved */
109
+ [15 ... 20] = true,
110
+ /* 21: reserved */
111
+ [22 ... 26] = true,
112
+ /* 27: reserved */
113
+ /* 28, 29: per-CPU CTI interrupts */
114
+ /* 30, 31: reserved */
115
+};
116
+
117
/* Create an alias region of @size bytes starting at @base
118
* which mirrors the memory starting at @orig.
119
*/
48
*/
120
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
49
void gicv3_redist_movall_lpis(GICv3CPUState *src, GICv3CPUState *dest);
121
int i;
50
+/**
122
51
+ * gicv3_redist_mov_vlpi:
123
assert(info->sram_banks <= MAX_SRAM_BANKS);
52
+ * @src: source redistributor
124
+ assert(info->num_cpus <= SSE_MAX_CPUS);
53
+ * @src_vptaddr: (guest) address of source VLPI table
125
54
+ * @dest: destination redistributor
126
memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
55
+ * @dest_vptaddr: (guest) address of destination VLPI table
127
56
+ * @irq: VLPI to update
128
- sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
57
+ * @doorbell: doorbell for destination (1023 for "no doorbell")
129
- TYPE_ARMV7M);
58
+ *
130
- qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type",
59
+ * Move the pending state of the specified VLPI from @src to @dest,
131
- ARM_CPU_TYPE_NAME("cortex-m33"));
60
+ * as required by the ITS VMOVI command.
132
+ for (i = 0; i < info->num_cpus; i++) {
61
+ */
133
+ char *name = g_strdup_printf("armv7m%d", i);
62
+void gicv3_redist_mov_vlpi(GICv3CPUState *src, uint64_t src_vptaddr,
134
+ sysbus_init_child_obj(obj, name, &s->armv7m[i], sizeof(s->armv7m),
63
+ GICv3CPUState *dest, uint64_t dest_vptaddr,
135
+ TYPE_ARMV7M);
64
+ int irq, int doorbell);
136
+ qdev_prop_set_string(DEVICE(&s->armv7m[i]), "cpu-type",
65
137
+ ARM_CPU_TYPE_NAME("cortex-m33"));
66
void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns);
138
+ g_free(name);
67
void gicv3_init_cpuif(GICv3State *s);
139
+ }
68
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
140
69
index XXXXXXX..XXXXXXX 100644
141
sysbus_init_child_obj(obj, "secctl", &s->secctl, sizeof(s->secctl),
70
--- a/hw/intc/arm_gicv3_its.c
142
TYPE_IOTKIT_SECCTL);
71
+++ b/hw/intc/arm_gicv3_its.c
143
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
72
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_vmovp(GICv3ITSState *s, const uint64_t *cmdpkt)
144
TYPE_SPLIT_IRQ, &error_abort, NULL);
73
return cbdata.result;
145
g_free(name);
146
}
147
+ if (info->num_cpus > 1) {
148
+ for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
149
+ if (irq_is_common[i]) {
150
+ char *name = g_strdup_printf("cpu-irq-splitter%d", i);
151
+ SplitIRQ *splitter = &s->cpu_irq_splitter[i];
152
+
153
+ object_initialize_child(obj, name, splitter, sizeof(*splitter),
154
+ TYPE_SPLIT_IRQ, &error_abort, NULL);
155
+ g_free(name);
156
+ }
157
+ }
158
+ }
159
}
74
}
160
75
161
static void armsse_exp_irq(void *opaque, int n, int level)
76
+static ItsCmdResult process_vmovi(GICv3ITSState *s, const uint64_t *cmdpkt)
77
+{
78
+ uint32_t devid, eventid, vpeid, doorbell;
79
+ bool doorbell_valid;
80
+ DTEntry dte;
81
+ ITEntry ite;
82
+ VTEntry old_vte, new_vte;
83
+ ItsCmdResult cmdres;
84
+
85
+ if (!its_feature_virtual(s)) {
86
+ return CMD_CONTINUE;
87
+ }
88
+
89
+ devid = FIELD_EX64(cmdpkt[0], VMOVI_0, DEVICEID);
90
+ eventid = FIELD_EX64(cmdpkt[1], VMOVI_1, EVENTID);
91
+ vpeid = FIELD_EX64(cmdpkt[1], VMOVI_1, VPEID);
92
+ doorbell_valid = FIELD_EX64(cmdpkt[2], VMOVI_2, D);
93
+ doorbell = FIELD_EX64(cmdpkt[2], VMOVI_2, DOORBELL);
94
+
95
+ trace_gicv3_its_cmd_vmovi(devid, eventid, vpeid, doorbell_valid, doorbell);
96
+
97
+ if (doorbell_valid && !valid_doorbell(doorbell)) {
98
+ qemu_log_mask(LOG_GUEST_ERROR,
99
+ "%s: invalid doorbell 0x%x\n", __func__, doorbell);
100
+ return CMD_CONTINUE;
101
+ }
102
+
103
+ cmdres = lookup_ite(s, __func__, devid, eventid, &ite, &dte);
104
+ if (cmdres != CMD_CONTINUE_OK) {
105
+ return cmdres;
106
+ }
107
+
108
+ if (ite.inttype != ITE_INTTYPE_VIRTUAL) {
109
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: ITE is not for virtual interrupt\n",
110
+ __func__);
111
+ return CMD_CONTINUE;
112
+ }
113
+
114
+ cmdres = lookup_vte(s, __func__, ite.vpeid, &old_vte);
115
+ if (cmdres != CMD_CONTINUE_OK) {
116
+ return cmdres;
117
+ }
118
+ cmdres = lookup_vte(s, __func__, vpeid, &new_vte);
119
+ if (cmdres != CMD_CONTINUE_OK) {
120
+ return cmdres;
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
+
137
+ /*
138
+ * Move the LPI from the old redistributor to the new one. We don't
139
+ * need to do anything if the guest somehow specified the
140
+ * same pending table for source and destination.
141
+ */
142
+ if (old_vte.vptaddr != new_vte.vptaddr) {
143
+ gicv3_redist_mov_vlpi(&s->gicv3->cpu[old_vte.rdbase],
144
+ old_vte.vptaddr << 16,
145
+ &s->gicv3->cpu[new_vte.rdbase],
146
+ new_vte.vptaddr << 16,
147
+ ite.intid,
148
+ ite.doorbell);
149
+ }
150
+
151
+ /* Update the ITE to the new VPEID and possibly doorbell values */
152
+ return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE_OK : CMD_STALL;
153
+}
154
+
155
static ItsCmdResult process_inv(GICv3ITSState *s, const uint64_t *cmdpkt)
162
{
156
{
163
- ARMSSE *s = ARMSSE(opaque);
157
uint32_t devid, eventid;
164
+ qemu_irq *irqarray = opaque;
158
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
165
159
case GITS_CMD_VMOVP:
166
- qemu_set_irq(s->exp_irqs[n], level);
160
result = process_vmovp(s, cmdpkt);
167
+ qemu_set_irq(irqarray[n], level);
161
break;
162
+ case GITS_CMD_VMOVI:
163
+ result = process_vmovi(s, cmdpkt);
164
+ break;
165
default:
166
trace_gicv3_its_cmd_unknown(cmd);
167
break;
168
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
169
index XXXXXXX..XXXXXXX 100644
170
--- a/hw/intc/arm_gicv3_redist.c
171
+++ b/hw/intc/arm_gicv3_redist.c
172
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_process_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr,
173
*/
168
}
174
}
169
175
170
static void armsse_mpcexp_status(void *opaque, int n, int level)
176
+void gicv3_redist_mov_vlpi(GICv3CPUState *src, uint64_t src_vptaddr,
171
@@ -XXX,XX +XXX,XX @@ static void armsse_mpcexp_status(void *opaque, int n, int level)
177
+ GICv3CPUState *dest, uint64_t dest_vptaddr,
172
qemu_set_irq(s->mpcexp_status_in[n], level);
178
+ int irq, int doorbell)
173
}
174
175
+static qemu_irq armsse_get_common_irq_in(ARMSSE *s, int irqno)
176
+{
179
+{
177
+ /*
180
+ /*
178
+ * Return a qemu_irq which can be used to signal IRQ n to
181
+ * The redistributor handling for moving a VLPI will be added
179
+ * all CPUs in the SSE.
182
+ * in a subsequent commit.
180
+ */
183
+ */
181
+ ARMSSEClass *asc = ARMSSE_GET_CLASS(s);
182
+ const ARMSSEInfo *info = asc->info;
183
+
184
+ assert(irq_is_common[irqno]);
185
+
186
+ if (info->num_cpus == 1) {
187
+ /* Only one CPU -- just connect directly to it */
188
+ return qdev_get_gpio_in(DEVICE(&s->armv7m[0]), irqno);
189
+ } else {
190
+ /* Connect to the splitter which feeds all CPUs */
191
+ return qdev_get_gpio_in(DEVICE(&s->cpu_irq_splitter[irqno]), 0);
192
+ }
193
+}
184
+}
194
+
185
+
195
static void armsse_realize(DeviceState *dev, Error **errp)
186
void gicv3_redist_inv_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr)
196
{
187
{
197
ARMSSE *s = ARMSSE(dev);
198
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
199
200
memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
201
202
- qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", s->exp_numirq + 32);
203
- /* In real hardware the initial Secure VTOR is set from the INITSVTOR0
204
- * register in the IoT Kit System Control Register block, and the
205
- * initial value of that is in turn specifiable by the FPGA that
206
- * instantiates the IoT Kit. In QEMU we don't implement this wrinkle,
207
- * and simply set the CPU's init-svtor to the IoT Kit default value.
208
- */
209
- qdev_prop_set_uint32(DEVICE(&s->armv7m), "init-svtor", 0x10000000);
210
- object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container),
211
- "memory", &err);
212
- if (err) {
213
- error_propagate(errp, err);
214
- return;
215
- }
216
- object_property_set_link(OBJECT(&s->armv7m), OBJECT(s), "idau", &err);
217
- if (err) {
218
- error_propagate(errp, err);
219
- return;
220
- }
221
- object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
222
- if (err) {
223
- error_propagate(errp, err);
224
- return;
225
+ for (i = 0; i < info->num_cpus; i++) {
226
+ DeviceState *cpudev = DEVICE(&s->armv7m[i]);
227
+ Object *cpuobj = OBJECT(&s->armv7m[i]);
228
+ int j;
229
+ char *gpioname;
230
+
231
+ qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + 32);
232
+ /*
233
+ * In real hardware the initial Secure VTOR is set from the INITSVTOR0
234
+ * register in the IoT Kit System Control Register block, and the
235
+ * initial value of that is in turn specifiable by the FPGA that
236
+ * instantiates the IoT Kit. In QEMU we don't implement this wrinkle,
237
+ * and simply set the CPU's init-svtor to the IoT Kit default value.
238
+ * In SSE-200 the situation is similar, except that the default value
239
+ * is a reset-time signal input. Typically a board using the SSE-200
240
+ * will have a system control processor whose boot firmware initializes
241
+ * the INITSVTOR* registers before powering up the CPUs in any case,
242
+ * so the hardware's default value doesn't matter. QEMU doesn't emulate
243
+ * the control processor, so instead we behave in the way that the
244
+ * firmware does. All boards currently known about have firmware that
245
+ * sets the INITSVTOR0 and INITSVTOR1 registers to 0x10000000, like the
246
+ * IoTKit default. We can make this more configurable if necessary.
247
+ */
248
+ qdev_prop_set_uint32(cpudev, "init-svtor", 0x10000000);
249
+ /*
250
+ * Start all CPUs except CPU0 powered down. In real hardware it is
251
+ * a configurable property of the SSE-200 which CPUs start powered up
252
+ * (via the CPUWAIT0_RST and CPUWAIT1_RST parameters), but since all
253
+ * the boards we care about start CPU0 and leave CPU1 powered off,
254
+ * we hard-code that for now. We can add QOM properties for this
255
+ * later if necessary.
256
+ */
257
+ if (i > 0) {
258
+ object_property_set_bool(cpuobj, true, "start-powered-off", &err);
259
+ if (err) {
260
+ error_propagate(errp, err);
261
+ return;
262
+ }
263
+ }
264
+ object_property_set_link(cpuobj, OBJECT(&s->container), "memory", &err);
265
+ if (err) {
266
+ error_propagate(errp, err);
267
+ return;
268
+ }
269
+ object_property_set_link(cpuobj, OBJECT(s), "idau", &err);
270
+ if (err) {
271
+ error_propagate(errp, err);
272
+ return;
273
+ }
274
+ object_property_set_bool(cpuobj, true, "realized", &err);
275
+ if (err) {
276
+ error_propagate(errp, err);
277
+ return;
278
+ }
279
+
280
+ /* Connect EXP_IRQ/EXP_CPUn_IRQ GPIOs to the NVIC's lines 32 and up */
281
+ s->exp_irqs[i] = g_new(qemu_irq, s->exp_numirq);
282
+ for (j = 0; j < s->exp_numirq; j++) {
283
+ s->exp_irqs[i][j] = qdev_get_gpio_in(cpudev, i + 32);
284
+ }
285
+ if (i == 0) {
286
+ gpioname = g_strdup("EXP_IRQ");
287
+ } else {
288
+ gpioname = g_strdup_printf("EXP_CPU%d_IRQ", i);
289
+ }
290
+ qdev_init_gpio_in_named_with_opaque(dev, armsse_exp_irq,
291
+ s->exp_irqs[i],
292
+ gpioname, s->exp_numirq);
293
+ g_free(gpioname);
294
}
295
296
- /* Connect our EXP_IRQ GPIOs to the NVIC's lines 32 and up. */
297
- s->exp_irqs = g_new(qemu_irq, s->exp_numirq);
298
- for (i = 0; i < s->exp_numirq; i++) {
299
- s->exp_irqs[i] = qdev_get_gpio_in(DEVICE(&s->armv7m), i + 32);
300
+ /* Wire up the splitters that connect common IRQs to all CPUs */
301
+ if (info->num_cpus > 1) {
302
+ for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
303
+ if (irq_is_common[i]) {
304
+ Object *splitter = OBJECT(&s->cpu_irq_splitter[i]);
305
+ DeviceState *devs = DEVICE(splitter);
306
+ int cpunum;
307
+
308
+ object_property_set_int(splitter, info->num_cpus,
309
+ "num-lines", &err);
310
+ if (err) {
311
+ error_propagate(errp, err);
312
+ return;
313
+ }
314
+ object_property_set_bool(splitter, true, "realized", &err);
315
+ if (err) {
316
+ error_propagate(errp, err);
317
+ return;
318
+ }
319
+ for (cpunum = 0; cpunum < info->num_cpus; cpunum++) {
320
+ DeviceState *cpudev = DEVICE(&s->armv7m[cpunum]);
321
+
322
+ qdev_connect_gpio_out(devs, cpunum,
323
+ qdev_get_gpio_in(cpudev, i));
324
+ }
325
+ }
326
+ }
327
}
328
- qdev_init_gpio_in_named(dev, armsse_exp_irq, "EXP_IRQ", s->exp_numirq);
329
330
/* Set up the big aliases first */
331
make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
332
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
333
return;
334
}
335
qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0,
336
- qdev_get_gpio_in(DEVICE(&s->armv7m), 9));
337
+ armsse_get_common_irq_in(s, 9));
338
339
/* Devices behind APB PPC0:
340
* 0x40000000: timer0
341
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
342
return;
343
}
344
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
345
- qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
346
+ armsse_get_common_irq_in(s, 3));
347
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0);
348
object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[0]", &err);
349
if (err) {
350
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
351
return;
352
}
353
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
354
- qdev_get_gpio_in(DEVICE(&s->armv7m), 4));
355
+ armsse_get_common_irq_in(s, 4));
356
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
357
object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[1]", &err);
358
if (err) {
359
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
360
return;
361
}
362
sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0,
363
- qdev_get_gpio_in(DEVICE(&s->armv7m), 5));
364
+ armsse_get_common_irq_in(s, 5));
365
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
366
object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err);
367
if (err) {
368
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
369
return;
370
}
371
qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
372
- qdev_get_gpio_in(DEVICE(&s->armv7m), 10));
373
+ armsse_get_common_irq_in(s, 10));
374
375
/* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */
376
377
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
378
return;
379
}
380
sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0,
381
- qdev_get_gpio_in(DEVICE(&s->armv7m), 2));
382
+ armsse_get_common_irq_in(s, 2));
383
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
384
object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err);
385
if (err) {
386
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
387
return;
388
}
389
sysbus_connect_irq(SYS_BUS_DEVICE(&s->nswatchdog), 0,
390
- qdev_get_gpio_in(DEVICE(&s->armv7m), 1));
391
+ armsse_get_common_irq_in(s, 1));
392
sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
393
394
qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq);
395
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
396
qdev_pass_gpios(dev_secctl, dev, "mscexp_clear");
397
qdev_pass_gpios(dev_secctl, dev, "mscexp_ns");
398
qdev_connect_gpio_out_named(dev_secctl, "msc_irq", 0,
399
- qdev_get_gpio_in(DEVICE(&s->armv7m), 11));
400
+ armsse_get_common_irq_in(s, 11));
401
402
/*
188
/*
403
* Expose our container region to the board model; this corresponds
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"
404
--
201
--
405
2.20.1
202
2.25.1
406
407
diff view generated by jsdifflib
New 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.
1
5
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
1
Add a model of the SSE-200, now we have put in all
1
The GICv4 extends the redistributor register map -- where GICv3
2
the code that lets us make it different from the IoTKit.
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
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.
3
11
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20190121185118.18550-22-peter.maydell@linaro.org
14
Message-id: 20220408141550.1271295-23-peter.maydell@linaro.org
7
---
15
---
8
include/hw/arm/armsse.h | 19 ++++++++++++++++---
16
hw/intc/gicv3_internal.h | 21 +++++++++++++++++++++
9
hw/arm/armsse.c | 12 ++++++++++++
17
include/hw/intc/arm_gicv3_common.h | 5 +++++
10
2 files changed, 28 insertions(+), 3 deletions(-)
18
hw/intc/arm_gicv3_common.c | 2 +-
19
hw/intc/arm_gicv3_redist.c | 8 ++++----
20
4 files changed, 31 insertions(+), 5 deletions(-)
11
21
12
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
22
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
13
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/armsse.h
24
--- a/hw/intc/gicv3_internal.h
15
+++ b/include/hw/arm/armsse.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
16
@@ -XXX,XX +XXX,XX @@
58
@@ -XXX,XX +XXX,XX @@
17
/*
59
18
- * ARM SSE (Subsystems for Embedded): IoTKit
60
#define GICV3_LPI_INTID_START 8192
19
+ * ARM SSE (Subsystems for Embedded): IoTKit, SSE-200
61
20
*
62
+/*
21
* Copyright (c) 2018 Linaro Limited
63
+ * The redistributor in GICv3 has two 64KB frames per CPU; in
22
* Written by Peter Maydell
64
+ * GICv4 it has four 64KB frames per CPU.
23
@@ -XXX,XX +XXX,XX @@
65
+ */
24
/*
66
#define GICV3_REDIST_SIZE 0x20000
25
* This is a model of the Arm "Subsystems for Embedded" family of
67
+#define GICV4_REDIST_SIZE 0x40000
26
* hardware, which include the IoT Kit and the SSE-050, SSE-100 and
68
27
- * SSE-200. Currently we model only the Arm IoT Kit which is documented in
69
/* Number of SGI target-list bits */
28
+ * SSE-200. Currently we model:
70
#define GICV3_TARGETLIST_BITS 16
29
+ * - the Arm IoT Kit which is documented in
71
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
30
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
31
- * It contains:
32
+ * - the SSE-200 which is documented in
33
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
34
+ *
35
+ * The IoTKit contains:
36
* a Cortex-M33
37
* the IDAU
38
* some timers and watchdogs
39
@@ -XXX,XX +XXX,XX @@
40
* a security controller
41
* a bus fabric which arranges that some parts of the address
42
* space are secure and non-secure aliases of each other
43
+ * The SSE-200 additionally contains:
44
+ * a second Cortex-M33
45
+ * two Message Handling Units (MHUs)
46
+ * an optional CryptoCell (which we do not model)
47
+ * more SRAM banks with associated MPCs
48
+ * multiple Power Policy Units (PPUs)
49
+ * a control interface for an icache for each CPU
50
+ * per-CPU identity and control register blocks
51
*
52
* QEMU interface:
53
* + QOM property "memory" is a MemoryRegion containing the devices provided
54
@@ -XXX,XX +XXX,XX @@
55
* them via the ARMSSE base class, so they have no IOTKIT() etc macros.
56
*/
57
#define TYPE_IOTKIT "iotkit"
58
+#define TYPE_SSE200 "sse-200"
59
60
/* We have an IRQ splitter and an OR gate input for each external PPC
61
* and the 2 internal PPCs
62
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
63
index XXXXXXX..XXXXXXX 100644
72
index XXXXXXX..XXXXXXX 100644
64
--- a/hw/arm/armsse.c
73
--- a/hw/intc/arm_gicv3_common.c
65
+++ b/hw/arm/armsse.c
74
+++ b/hw/intc/arm_gicv3_common.c
66
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
75
@@ -XXX,XX +XXX,XX @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
67
.has_cpusecctrl = false,
76
68
.has_cpuid = false,
77
memory_region_init_io(&region->iomem, OBJECT(s),
69
},
78
ops ? &ops[1] : NULL, region, name,
70
+ {
79
- s->redist_region_count[i] * GICV3_REDIST_SIZE);
71
+ .name = TYPE_SSE200,
80
+ s->redist_region_count[i] * gicv3_redist_size(s));
72
+ .sram_banks = 4,
81
sysbus_init_mmio(sbd, &region->iomem);
73
+ .num_cpus = 2,
82
g_free(name);
74
+ .sys_version = 0x22041743,
83
}
75
+ .sys_config_format = SSE200Format,
84
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
76
+ .has_mhus = true,
85
index XXXXXXX..XXXXXXX 100644
77
+ .has_ppus = true,
86
--- a/hw/intc/arm_gicv3_redist.c
78
+ .has_cachectrl = true,
87
+++ b/hw/intc/arm_gicv3_redist.c
79
+ .has_cpusecctrl = true,
88
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data,
80
+ .has_cpuid = true,
89
* in the memory map); if so then the GIC has multiple MemoryRegions
81
+ },
90
* for the redistributors.
82
};
91
*/
83
92
- cpuidx = region->cpuidx + offset / GICV3_REDIST_SIZE;
84
static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
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
85
--
110
--
86
2.20.1
111
2.25.1
87
88
diff view generated by jsdifflib
1
The Arm SSE-200 Subsystem for Embedded is a revised and
1
Implement the new GICv4 redistributor registers: GICR_VPROPBASER
2
extended version of the older IoTKit SoC. Prepare for
2
and GICR_VPENDBASER; for the moment we implement these as simple
3
adding a model of it by refactoring the IoTKit code into
3
reads-as-written stubs, together with the necessary migration
4
an abstract base class which contains the functionality,
4
and reset handling.
5
driven by a class data block specific to each subclass.
5
6
(This is the same approach used by the existing bcm283x
6
We don't put ID-register checks on the handling of these registers,
7
SoC family implementation.)
7
because they are all in the only-in-v4 extra register frames, so
8
they're not accessible in a GICv3.
8
9
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20190121185118.18550-6-peter.maydell@linaro.org
12
Message-id: 20220408141550.1271295-24-peter.maydell@linaro.org
13
---
13
---
14
include/hw/arm/iotkit.h | 22 +++++++++++++++++-----
14
hw/intc/gicv3_internal.h | 21 +++++++++++
15
hw/arm/iotkit.c | 34 +++++++++++++++++++++++++++++-----
15
include/hw/intc/arm_gicv3_common.h | 3 ++
16
2 files changed, 46 insertions(+), 10 deletions(-)
16
hw/intc/arm_gicv3_common.c | 22 ++++++++++++
17
hw/intc/arm_gicv3_redist.c | 56 ++++++++++++++++++++++++++++++
18
4 files changed, 102 insertions(+)
17
19
18
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
20
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
19
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/iotkit.h
22
--- a/hw/intc/gicv3_internal.h
21
+++ b/include/hw/arm/iotkit.h
23
+++ b/hw/intc/gicv3_internal.h
22
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@
23
#include "hw/or-irq.h"
25
* Redistributor frame offsets from RD_base
24
#include "hw/core/split-irq.h"
26
*/
25
27
#define GICR_SGI_OFFSET 0x10000
26
-#define TYPE_ARMSSE "iotkit"
28
+#define GICR_VLPI_OFFSET 0x20000
27
+#define TYPE_ARMSSE "arm-sse"
28
#define ARMSSE(obj) OBJECT_CHECK(ARMSSE, (obj), TYPE_ARMSSE)
29
29
30
/*
30
/*
31
- * For the moment TYPE_IOTKIT is a synonym for TYPE_ARMSSE (and the
31
* Redistributor registers, offsets from RD_base
32
- * latter's underlying name is left as "iotkit"); in a later
33
- * commit it will become a subclass of TYPE_ARMSSE.
34
+ * These type names are for specific IoTKit subsystems; other than
35
+ * instantiating them, code using these devices should always handle
36
+ * them via the ARMSSE base class, so they have no IOTKIT() etc macros.
37
*/
38
-#define TYPE_IOTKIT TYPE_ARMSSE
39
+#define TYPE_IOTKIT "iotkit"
40
41
/* We have an IRQ splitter and an OR gate input for each external PPC
42
* and the 2 internal PPCs
43
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
44
uint32_t mainclk_frq;
45
} ARMSSE;
46
47
+typedef struct ARMSSEInfo ARMSSEInfo;
48
+
49
+typedef struct ARMSSEClass {
50
+ DeviceClass parent_class;
51
+ const ARMSSEInfo *info;
52
+} ARMSSEClass;
53
+
54
+#define ARMSSE_CLASS(klass) \
55
+ OBJECT_CLASS_CHECK(ARMSSEClass, (klass), TYPE_ARMSSE)
56
+#define ARMSSE_GET_CLASS(obj) \
57
+ OBJECT_GET_CLASS(ARMSSEClass, (obj), TYPE_ARMSSE)
58
+
59
#endif
60
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/arm/iotkit.c
63
+++ b/hw/arm/iotkit.c
64
@@ -XXX,XX +XXX,XX @@
32
@@ -XXX,XX +XXX,XX @@
65
#include "hw/arm/iotkit.h"
33
#define GICR_IGRPMODR0 (GICR_SGI_OFFSET + 0x0D00)
66
#include "hw/arm/arm.h"
34
#define GICR_NSACR (GICR_SGI_OFFSET + 0x0E00)
67
35
68
+struct ARMSSEInfo {
36
+/* VLPI redistributor registers, offsets from VLPI_base */
69
+ const char *name;
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
+ }
70
+};
105
+};
71
+
106
+
72
+static const ARMSSEInfo armsse_variants[] = {
107
static const VMStateDescription vmstate_gicv3_cpu = {
73
+ {
108
.name = "arm_gicv3_cpu",
74
+ .name = TYPE_IOTKIT,
109
.version_id = 1,
75
+ },
110
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_gicv3_cpu = {
76
+};
111
.subsections = (const VMStateDescription * []) {
77
+
112
&vmstate_gicv3_cpu_virt,
78
/* Clock frequency in HZ of the 32KHz "slow clock" */
113
&vmstate_gicv3_cpu_sre_el1,
79
#define S32KCLK (32 * 1000)
114
+ &vmstate_gicv3_gicv4,
80
115
NULL
81
@@ -XXX,XX +XXX,XX @@ static void iotkit_class_init(ObjectClass *klass, void *data)
82
{
83
DeviceClass *dc = DEVICE_CLASS(klass);
84
IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
85
+ ARMSSEClass *asc = ARMSSE_CLASS(klass);
86
87
dc->realize = iotkit_realize;
88
dc->vmsd = &iotkit_vmstate;
89
dc->props = iotkit_properties;
90
dc->reset = iotkit_reset;
91
iic->check = iotkit_idau_check;
92
+ asc->info = data;
93
}
94
95
-static const TypeInfo iotkit_info = {
96
+static const TypeInfo armsse_info = {
97
.name = TYPE_ARMSSE,
98
.parent = TYPE_SYS_BUS_DEVICE,
99
.instance_size = sizeof(ARMSSE),
100
.instance_init = iotkit_init,
101
- .class_init = iotkit_class_init,
102
+ .abstract = true,
103
.interfaces = (InterfaceInfo[]) {
104
{ TYPE_IDAU_INTERFACE },
105
{ }
106
}
116
}
107
};
117
};
108
118
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_reset(DeviceState *dev)
109
-static void iotkit_register_types(void)
119
cs->gicr_waker = GICR_WAKER_ProcessorSleep | GICR_WAKER_ChildrenAsleep;
110
+static void armsse_register_types(void)
120
cs->gicr_propbaser = 0;
111
{
121
cs->gicr_pendbaser = 0;
112
- type_register_static(&iotkit_info);
122
+ cs->gicr_vpropbaser = 0;
113
+ int i;
123
+ cs->gicr_vpendbaser = 0;
114
+
124
/* If we're resetting a TZ-aware GIC as if secure firmware
115
+ type_register_static(&armsse_info);
125
* had set it up ready to start a kernel in non-secure, we
116
+
126
* need to set interrupts to group 1 so the kernel can use them.
117
+ for (i = 0; i < ARRAY_SIZE(armsse_variants); i++) {
127
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
118
+ TypeInfo ti = {
128
index XXXXXXX..XXXXXXX 100644
119
+ .name = armsse_variants[i].name,
129
--- a/hw/intc/arm_gicv3_redist.c
120
+ .parent = TYPE_ARMSSE,
130
+++ b/hw/intc/arm_gicv3_redist.c
121
+ .class_init = iotkit_class_init,
131
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_readl(GICv3CPUState *cs, hwaddr offset,
122
+ .class_data = (void *)&armsse_variants[i],
132
case GICR_IDREGS ... GICR_IDREGS + 0x2f:
123
+ };
133
*data = gicv3_idreg(offset - GICR_IDREGS, GICV3_PIDR0_REDIST);
124
+ type_register(&ti);
134
return MEMTX_OK;
125
+ }
135
+ /*
126
}
136
+ * VLPI frame registers. We don't need a version check for
127
137
+ * VPROPBASER and VPENDBASER because gicv3_redist_size() will
128
-type_init(iotkit_register_types);
138
+ * prevent pre-v4 GIC from passing us offsets this high.
129
+type_init(armsse_register_types);
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
}
130
--
215
--
131
2.20.1
216
2.25.1
132
133
diff view generated by jsdifflib
1
Add a model of the MPS2 FPGA image described in Application Note
1
The function gicv3_cpuif_virt_update() currently sets all of vIRQ,
2
AN521. This is identical to the AN505 image, except that it uses
2
vFIQ and the maintenance interrupt. This implies that it has to be
3
the SSE-200 rather than the IoTKit and so has two Cortex-M33 CPUs.
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.
4
12
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20190121185118.18550-24-peter.maydell@linaro.org
15
Message-id: 20220408141550.1271295-25-peter.maydell@linaro.org
8
---
16
---
9
hw/arm/mps2-tz.c | 38 ++++++++++++++++++++++++++++++++++++--
17
hw/intc/gicv3_internal.h | 11 +++++++
10
1 file changed, 36 insertions(+), 2 deletions(-)
18
hw/intc/arm_gicv3_cpuif.c | 64 ++++++++++++++++++++++++---------------
19
hw/intc/trace-events | 3 +-
20
3 files changed, 53 insertions(+), 25 deletions(-)
11
21
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
22
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
13
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/mps2-tz.c
24
--- a/hw/intc/gicv3_internal.h
15
+++ b/hw/arm/mps2-tz.c
25
+++ b/hw/intc/gicv3_internal.h
16
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@ void gicv3_init_cpuif(GICv3State *s);
17
* as seen by the guest depend significantly on the FPGA image.
27
*/
18
* This source file covers the following FPGA images, for TrustZone cores:
28
void gicv3_cpuif_update(GICv3CPUState *cs);
19
* "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
29
20
+ * "mps2-an521" -- Dual Cortex-M33 as documented in Application Note AN521
30
+/*
21
*
31
+ * gicv3_cpuif_virt_irq_fiq_update:
22
* Links to the TRM for the board itself and to the various Application
32
+ * @cs: GICv3CPUState for the CPU to update
23
* Notes which document the FPGA images can be found here:
24
@@ -XXX,XX +XXX,XX @@
25
* http://infocenter.arm.com/help/topic/com.arm.doc.100112_0200_06_en/versatile_express_cortex_m_prototyping_systems_v2m_mps2_and_v2m_mps2plus_technical_reference_100112_0200_06_en.pdf
26
* Application Note AN505:
27
* http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
28
+ * Application Note AN521:
29
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0521c/index.html
30
*
31
* The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
32
* (ARM ECM0601256) for the details of some of the device layout:
33
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
34
+ * Similarly, the AN521 uses the SSE-200, and the SSE-200 TRM defines
35
+ * most of the device layout:
36
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
37
+ *
33
+ *
38
*/
34
+ * Recalculate whether to assert the virtual IRQ or FIQ lines after
39
35
+ * a change to the current highest priority pending virtual interrupt.
40
#include "qemu/osdep.h"
36
+ * Note that this does not recalculate and change the maintenance
41
@@ -XXX,XX +XXX,XX @@ typedef struct {
37
+ * interrupt status (for that, see gicv3_cpuif_virt_update()).
42
MachineClass parent;
38
+ */
43
MPS2TZFPGAType fpga_type;
39
+void gicv3_cpuif_virt_irq_fiq_update(GICv3CPUState *cs);
44
uint32_t scc_id;
40
+
45
+ const char *armsse_type;
41
static inline uint32_t gicv3_iidr(void)
46
} MPS2TZMachineClass;
42
{
47
43
/* Return the Implementer Identification Register value
48
typedef struct {
44
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
49
@@ -XXX,XX +XXX,XX @@ typedef struct {
45
index XXXXXXX..XXXXXXX 100644
50
46
--- a/hw/intc/arm_gicv3_cpuif.c
51
#define TYPE_MPS2TZ_MACHINE "mps2tz"
47
+++ b/hw/intc/arm_gicv3_cpuif.c
52
#define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
48
@@ -XXX,XX +XXX,XX @@ static uint32_t maintenance_interrupt_state(GICv3CPUState *cs)
53
+#define TYPE_MPS2TZ_AN521_MACHINE MACHINE_TYPE_NAME("mps2-an521")
49
return value;
54
50
}
55
#define MPS2TZ_MACHINE(obj) \
51
56
OBJECT_CHECK(MPS2TZMachineState, obj, TYPE_MPS2TZ_MACHINE)
52
-static void gicv3_cpuif_virt_update(GICv3CPUState *cs)
57
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
53
+void gicv3_cpuif_virt_irq_fiq_update(GICv3CPUState *cs)
54
{
55
- /* Tell the CPU about any pending virtual interrupts or
56
- * maintenance interrupts, following a change to the state
57
- * of the CPU interface relevant to virtual interrupts.
58
- *
59
- * CAUTION: this function will call qemu_set_irq() on the
60
- * CPU maintenance IRQ line, which is typically wired up
61
- * to the GIC as a per-CPU interrupt. This means that it
62
- * will recursively call back into the GIC code via
63
- * gicv3_redist_set_irq() and thus into the CPU interface code's
64
- * gicv3_cpuif_update(). It is therefore important that this
65
- * function is only called as the final action of a CPU interface
66
- * register write implementation, after all the GIC state
67
- * fields have been updated. gicv3_cpuif_update() also must
68
- * not cause this function to be called, but that happens
69
- * naturally as a result of there being no architectural
70
- * linkage between the physical and virtual GIC logic.
71
+ /*
72
+ * Tell the CPU about any pending virtual interrupts.
73
+ * This should only be called for changes that affect the
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
*/
80
int idx;
81
int irqlevel = 0;
82
int fiqlevel = 0;
83
- int maintlevel = 0;
84
- ARMCPU *cpu = ARM_CPU(cs->cpu);
85
86
idx = hppvi_index(cs);
87
trace_gicv3_cpuif_virt_update(gicv3_redist_affid(cs), idx);
88
@@ -XXX,XX +XXX,XX @@ static void gicv3_cpuif_virt_update(GICv3CPUState *cs)
89
}
58
}
90
}
59
91
60
sysbus_init_child_obj(OBJECT(machine), "iotkit", &mms->iotkit,
92
+ trace_gicv3_cpuif_virt_set_irqs(gicv3_redist_affid(cs), fiqlevel, irqlevel);
61
- sizeof(mms->iotkit), TYPE_IOTKIT);
93
+ qemu_set_irq(cs->parent_vfiq, fiqlevel);
62
+ sizeof(mms->iotkit), mmc->armsse_type);
94
+ qemu_set_irq(cs->parent_virq, irqlevel);
63
iotkitdev = DEVICE(&mms->iotkit);
64
object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory),
65
"memory", &error_abort);
66
@@ -XXX,XX +XXX,XX @@ static void mps2tz_class_init(ObjectClass *oc, void *data)
67
IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(oc);
68
69
mc->init = mps2tz_common_init;
70
- mc->max_cpus = 1;
71
iic->check = mps2_tz_idau_check;
72
}
73
74
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
75
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
76
77
mc->desc = "ARM MPS2 with AN505 FPGA image for Cortex-M33";
78
+ mc->default_cpus = 1;
79
+ mc->min_cpus = mc->default_cpus;
80
+ mc->max_cpus = mc->default_cpus;
81
mmc->fpga_type = FPGA_AN505;
82
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
83
mmc->scc_id = 0x41045050;
84
+ mmc->armsse_type = TYPE_IOTKIT;
85
+}
95
+}
86
+
96
+
87
+static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
97
+static void gicv3_cpuif_virt_update(GICv3CPUState *cs)
88
+{
98
+{
89
+ MachineClass *mc = MACHINE_CLASS(oc);
99
+ /*
90
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
100
+ * Tell the CPU about any pending virtual interrupts or
101
+ * maintenance interrupts, following a change to the state
102
+ * of the CPU interface relevant to virtual interrupts.
103
+ *
104
+ * CAUTION: this function will call qemu_set_irq() on the
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
+ */
117
+ ARMCPU *cpu = ARM_CPU(cs->cpu);
118
+ int maintlevel = 0;
91
+
119
+
92
+ mc->desc = "ARM MPS2 with AN521 FPGA image for dual Cortex-M33";
120
+ gicv3_cpuif_virt_irq_fiq_update(cs);
93
+ mc->default_cpus = 2;
121
+
94
+ mc->min_cpus = mc->default_cpus;
122
if ((cs->ich_hcr_el2 & ICH_HCR_EL2_EN) &&
95
+ mc->max_cpus = mc->default_cpus;
123
maintenance_interrupt_state(cs) != 0) {
96
+ mmc->fpga_type = FPGA_AN521;
124
maintlevel = 1;
97
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
125
}
98
+ mmc->scc_id = 0x41045210;
126
99
+ mmc->armsse_type = TYPE_SSE200;
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);
100
}
134
}
101
135
102
static const TypeInfo mps2tz_info = {
136
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
103
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2tz_an505_info = {
137
index XXXXXXX..XXXXXXX 100644
104
.class_init = mps2tz_an505_class_init,
138
--- a/hw/intc/trace-events
105
};
139
+++ b/hw/intc/trace-events
106
140
@@ -XXX,XX +XXX,XX @@ gicv3_icv_dir_write(uint32_t cpu, uint64_t val) "GICv3 ICV_DIR write cpu 0x%x va
107
+static const TypeInfo mps2tz_an521_info = {
141
gicv3_icv_iar_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_IAR%d read cpu 0x%x value 0x%" PRIx64
108
+ .name = TYPE_MPS2TZ_AN521_MACHINE,
142
gicv3_icv_eoir_write(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_EOIR%d write cpu 0x%x value 0x%" PRIx64
109
+ .parent = TYPE_MPS2TZ_MACHINE,
143
gicv3_cpuif_virt_update(uint32_t cpuid, int idx) "GICv3 CPU i/f 0x%x virt HPPI update LR index %d"
110
+ .class_init = mps2tz_an521_class_init,
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"
111
+};
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"
112
+
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"
113
static void mps2tz_machine_init(void)
147
114
{
148
# arm_gicv3_dist.c
115
type_register_static(&mps2tz_info);
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"
116
type_register_static(&mps2tz_an505_info);
117
+ type_register_static(&mps2tz_an521_info);
118
}
119
120
type_init(mps2tz_machine_init);
121
--
150
--
122
2.20.1
151
2.25.1
123
124
diff view generated by jsdifflib
1
Expose "start-powered-off" as a property of the ARMv7M container,
1
The CPU interface changes to support vLPIs are fairly minor:
2
which we just pass through to the CPU object in the same way that we
2
in the parts of the code that currently look at the list registers
3
do for "init-svtor" and "idau". (We want this for the SSE-200, which
3
to determine the highest priority pending virtual interrupt, we
4
powers up only the first CPU at reset and leaves the second powered
4
must also look at the highest priority pending vLPI. To do this
5
down.)
5
we change hppvi_index() to check the vLPI and return a special-case
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.
6
9
7
As with the other CPU properties here, we can't just use alias
10
This commit includes two interfaces with the as-yet-unwritten
8
properties, because the CPU QOM object is not created until armv7m
11
redistributor code:
9
realize time.
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
10
18
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20190121185118.18550-4-peter.maydell@linaro.org
21
Message-id: 20220408141550.1271295-26-peter.maydell@linaro.org
14
---
22
---
15
include/hw/arm/armv7m.h | 1 +
23
hw/intc/gicv3_internal.h | 13 ++++
16
hw/arm/armv7m.c | 10 ++++++++++
24
include/hw/intc/arm_gicv3_common.h | 3 +
17
2 files changed, 11 insertions(+)
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(-)
18
30
19
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
31
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
20
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/arm/armv7m.h
33
--- a/hw/intc/gicv3_internal.h
22
+++ b/include/hw/arm/armv7m.h
34
+++ b/hw/intc/gicv3_internal.h
23
@@ -XXX,XX +XXX,XX @@ typedef struct ARMv7MState {
35
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level);
24
Object *idau;
36
*/
25
uint32_t init_svtor;
37
void gicv3_redist_process_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr,
26
bool enable_bitband;
38
int doorbell, int level);
27
+ bool start_powered_off;
39
+/**
28
} ARMv7MState;
40
+ * gicv3_redist_vlpi_pending:
29
41
+ * @cs: GICv3CPUState
30
#endif
42
+ * @irq: (virtual) interrupt number
31
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
43
+ * @level: level to set @irq to
32
index XXXXXXX..XXXXXXX 100644
44
+ *
33
--- a/hw/arm/armv7m.c
45
+ * Set/clear the pending status of a virtual LPI in the vLPI table
34
+++ b/hw/arm/armv7m.c
46
+ * that this redistributor is currently using. (The difference between
35
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
47
+ * this and gicv3_redist_process_vlpi() is that this is called from
36
return;
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)
37
}
119
}
38
}
120
}
39
+ if (object_property_find(OBJECT(s->cpu), "start-powered-off", NULL)) {
121
40
+ object_property_set_bool(OBJECT(s->cpu), s->start_powered_off,
122
+ /*
41
+ "start-powered-off", &err);
123
+ * "no pending vLPI" is indicated with prio = 0xff, which always
42
+ if (err != NULL) {
124
+ * fails the priority check here. vLPIs are only considered
43
+ error_propagate(errp, err);
125
+ * when we are in Non-Secure state.
44
+ return;
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
+ }
45
+ }
136
+ }
46
+ }
137
+ }
47
138
+
48
/*
139
return idx;
49
* Tell the CPU where the NVIC is; it will fail realize if it doesn't
140
}
50
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
141
51
DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
142
@@ -XXX,XX +XXX,XX @@ static bool icv_hppi_can_preempt(GICv3CPUState *cs, uint64_t lr)
52
DEFINE_PROP_UINT32("init-svtor", ARMv7MState, init_svtor, 0),
143
return false;
53
DEFINE_PROP_BOOL("enable-bitband", ARMv7MState, enable_bitband, false),
144
}
54
+ DEFINE_PROP_BOOL("start-powered-off", ARMv7MState, start_powered_off,
145
55
+ false),
146
+static bool icv_hppvlpi_can_preempt(GICv3CPUState *cs)
56
DEFINE_PROP_END_OF_LIST(),
147
+{
57
};
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"
58
301
59
--
302
--
60
2.20.1
303
2.25.1
61
62
diff view generated by jsdifflib
1
The Arm IoTKit was effectively the forerunner of a series of
1
The maintenance interrupt state depends only on:
2
subsystems for embedded SoCs, named the SSE-050, SSE-100 and SSE-200:
2
* ICH_HCR_EL2
3
https://developer.arm.com/products/system-design/subsystems
3
* ICH_LR<n>_EL2
4
These are generally quite similar, though later iterations have
4
* ICH_VMCR_EL2 fields VENG0 and VENG1
5
extra devices that earlier ones do not.
6
5
7
We want to add a model of the SSE-200, which means refactoring the
6
Now we have a separate function that updates only the vIRQ and vFIQ
8
IoTKit code into an abstract base class and subclasses (using the
7
lines, use that in places that only change state that affects vIRQ
9
same design that the bcm283x SoC and Aspeed SoC family
8
and vFIQ but not the maintenance interrupt.
10
implementations do). As a first step, rename the IoTKit struct and
11
QOM macros to ARMSSE, which is what we're going to name the base
12
class. We temporarily retain TYPE_IOTKIT to avoid changing the
13
code that instantiates a TYPE_IOTKIT device here and then changing
14
it back again when it is re-introduced as a subclass.
15
9
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20190121185118.18550-5-peter.maydell@linaro.org
12
Message-id: 20220408141550.1271295-27-peter.maydell@linaro.org
20
---
13
---
21
include/hw/arm/iotkit.h | 22 ++++++++++-----
14
hw/intc/arm_gicv3_cpuif.c | 10 +++++-----
22
hw/arm/iotkit.c | 59 +++++++++++++++++++++--------------------
15
1 file changed, 5 insertions(+), 5 deletions(-)
23
hw/arm/mps2-tz.c | 2 +-
24
3 files changed, 47 insertions(+), 36 deletions(-)
25
16
26
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
17
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
27
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
28
--- a/include/hw/arm/iotkit.h
19
--- a/hw/intc/arm_gicv3_cpuif.c
29
+++ b/include/hw/arm/iotkit.h
20
+++ b/hw/intc/arm_gicv3_cpuif.c
30
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static void icv_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
31
/*
22
32
- * ARM IoT Kit
23
cs->ich_apr[grp][regno] = value & 0xFFFFFFFFU;
33
+ * ARM SSE (Subsystems for Embedded): IoTKit
24
34
*
25
- gicv3_cpuif_virt_update(cs);
35
* Copyright (c) 2018 Linaro Limited
26
+ gicv3_cpuif_virt_irq_fiq_update(cs);
36
* Written by Peter Maydell
27
return;
37
@@ -XXX,XX +XXX,XX @@
38
* (at your option) any later version.
39
*/
40
41
-/* This is a model of the Arm IoT Kit which is documented in
42
+/*
43
+ * This is a model of the Arm "Subsystems for Embedded" family of
44
+ * hardware, which include the IoT Kit and the SSE-050, SSE-100 and
45
+ * SSE-200. Currently we model only the Arm IoT Kit which is documented in
46
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
47
* It contains:
48
* a Cortex-M33
49
@@ -XXX,XX +XXX,XX @@
50
#include "hw/or-irq.h"
51
#include "hw/core/split-irq.h"
52
53
-#define TYPE_IOTKIT "iotkit"
54
-#define IOTKIT(obj) OBJECT_CHECK(IoTKit, (obj), TYPE_IOTKIT)
55
+#define TYPE_ARMSSE "iotkit"
56
+#define ARMSSE(obj) OBJECT_CHECK(ARMSSE, (obj), TYPE_ARMSSE)
57
+
58
+/*
59
+ * For the moment TYPE_IOTKIT is a synonym for TYPE_ARMSSE (and the
60
+ * latter's underlying name is left as "iotkit"); in a later
61
+ * commit it will become a subclass of TYPE_ARMSSE.
62
+ */
63
+#define TYPE_IOTKIT TYPE_ARMSSE
64
65
/* We have an IRQ splitter and an OR gate input for each external PPC
66
* and the 2 internal PPCs
67
@@ -XXX,XX +XXX,XX @@
68
#define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
69
#define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
70
71
-typedef struct IoTKit {
72
+typedef struct ARMSSE {
73
/*< private >*/
74
SysBusDevice parent_obj;
75
76
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
77
MemoryRegion *board_memory;
78
uint32_t exp_numirq;
79
uint32_t mainclk_frq;
80
-} IoTKit;
81
+} ARMSSE;
82
83
#endif
84
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/hw/arm/iotkit.c
87
+++ b/hw/arm/iotkit.c
88
@@ -XXX,XX +XXX,XX @@
89
/*
90
- * Arm IoT Kit
91
+ * Arm SSE (Subsystems for Embedded): IoTKit
92
*
93
* Copyright (c) 2018 Linaro Limited
94
* Written by Peter Maydell
95
@@ -XXX,XX +XXX,XX @@
96
/* Create an alias region of @size bytes starting at @base
97
* which mirrors the memory starting at @orig.
98
*/
99
-static void make_alias(IoTKit *s, MemoryRegion *mr, const char *name,
100
+static void make_alias(ARMSSE *s, MemoryRegion *mr, const char *name,
101
hwaddr base, hwaddr size, hwaddr orig)
102
{
103
memory_region_init_alias(mr, NULL, name, &s->container, orig, size);
104
@@ -XXX,XX +XXX,XX @@ static void irq_status_forwarder(void *opaque, int n, int level)
105
106
static void nsccfg_handler(void *opaque, int n, int level)
107
{
108
- IoTKit *s = IOTKIT(opaque);
109
+ ARMSSE *s = ARMSSE(opaque);
110
111
s->nsccfg = level;
112
}
28
}
113
29
114
-static void iotkit_forward_ppc(IoTKit *s, const char *ppcname, int ppcnum)
30
@@ -XXX,XX +XXX,XX @@ static void icv_bpr_write(CPUARMState *env, const ARMCPRegInfo *ri,
115
+static void iotkit_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
31
116
{
32
write_vbpr(cs, grp, value);
117
/* Each of the 4 AHB and 4 APB PPCs that might be present in a
33
118
- * system using the IoTKit has a collection of control lines which
34
- gicv3_cpuif_virt_update(cs);
119
+ * system using the ARMSSE has a collection of control lines which
35
+ gicv3_cpuif_virt_irq_fiq_update(cs);
120
* are provided by the security controller and which we want to
121
- * expose as control lines on the IoTKit device itself, so the
122
- * code using the IoTKit can wire them up to the PPCs.
123
+ * expose as control lines on the ARMSSE device itself, so the
124
+ * code using the ARMSSE can wire them up to the PPCs.
125
*/
126
SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum];
127
DeviceState *iotkitdev = DEVICE(s);
128
@@ -XXX,XX +XXX,XX @@ static void iotkit_forward_ppc(IoTKit *s, const char *ppcname, int ppcnum)
129
g_free(name);
130
}
36
}
131
37
132
-static void iotkit_forward_sec_resp_cfg(IoTKit *s)
38
static uint64_t icv_pmr_read(CPUARMState *env, const ARMCPRegInfo *ri)
133
+static void iotkit_forward_sec_resp_cfg(ARMSSE *s)
39
@@ -XXX,XX +XXX,XX @@ static void icv_pmr_write(CPUARMState *env, const ARMCPRegInfo *ri,
134
{
40
cs->ich_vmcr_el2 = deposit64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VPMR_SHIFT,
135
/* Forward the 3rd output from the splitter device as a
41
ICH_VMCR_EL2_VPMR_LENGTH, value);
136
* named GPIO output of the iotkit object.
42
137
@@ -XXX,XX +XXX,XX @@ static void iotkit_forward_sec_resp_cfg(IoTKit *s)
43
- gicv3_cpuif_virt_update(cs);
138
44
+ gicv3_cpuif_virt_irq_fiq_update(cs);
139
static void iotkit_init(Object *obj)
140
{
141
- IoTKit *s = IOTKIT(obj);
142
+ ARMSSE *s = ARMSSE(obj);
143
int i;
144
145
memory_region_init(&s->container, obj, "iotkit-container", UINT64_MAX);
146
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
147
148
static void iotkit_exp_irq(void *opaque, int n, int level)
149
{
150
- IoTKit *s = IOTKIT(opaque);
151
+ ARMSSE *s = ARMSSE(opaque);
152
153
qemu_set_irq(s->exp_irqs[n], level);
154
}
45
}
155
46
156
static void iotkit_mpcexp_status(void *opaque, int n, int level)
47
static uint64_t icv_igrpen_read(CPUARMState *env, const ARMCPRegInfo *ri)
157
{
48
@@ -XXX,XX +XXX,XX @@ static void icv_ctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
158
- IoTKit *s = IOTKIT(opaque);
49
cs->ich_vmcr_el2 = deposit64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VEOIM_SHIFT,
159
+ ARMSSE *s = ARMSSE(opaque);
50
1, value & ICC_CTLR_EL1_EOIMODE ? 1 : 0);
160
qemu_set_irq(s->mpcexp_status_in[n], level);
51
52
- gicv3_cpuif_virt_update(cs);
53
+ gicv3_cpuif_virt_irq_fiq_update(cs);
161
}
54
}
162
55
163
static void iotkit_realize(DeviceState *dev, Error **errp)
56
static uint64_t icv_rpr_read(CPUARMState *env, const ARMCPRegInfo *ri)
164
{
57
@@ -XXX,XX +XXX,XX @@ static void ich_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
165
- IoTKit *s = IOTKIT(dev);
58
trace_gicv3_ich_ap_write(ri->crm & 1, regno, gicv3_redist_affid(cs), value);
166
+ ARMSSE *s = ARMSSE(dev);
59
167
int i;
60
cs->ich_apr[grp][regno] = value & 0xFFFFFFFFU;
168
MemoryRegion *mr;
61
- gicv3_cpuif_virt_update(cs);
169
Error *err = NULL;
62
+ gicv3_cpuif_virt_irq_fiq_update(cs);
170
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
171
* devices exist in both address spaces but with hard-wired security
172
* permissions that will cause the CPU to fault for non-secure accesses.
173
*
174
- * The IoTKit has an IDAU (Implementation Defined Access Unit),
175
+ * The ARMSSE has an IDAU (Implementation Defined Access Unit),
176
* which specifies hard-wired security permissions for different
177
- * areas of the physical address space. For the IoTKit IDAU, the
178
+ * areas of the physical address space. For the ARMSSE IDAU, the
179
* top 4 bits of the physical address are the IDAU region ID, and
180
* if bit 28 (ie the lowest bit of the ID) is 0 then this is an NS
181
* region, otherwise it is an S region.
182
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
183
* 0x20000000..0x2007ffff 32KB FPGA block RAM
184
* 0x30000000..0x3fffffff alias of 0x20000000..0x2fffffff
185
* 0x40000000..0x4000ffff base peripheral region 1
186
- * 0x40010000..0x4001ffff CPU peripherals (none for IoTKit)
187
+ * 0x40010000..0x4001ffff CPU peripherals (none for ARMSSE)
188
* 0x40020000..0x4002ffff system control element peripherals
189
* 0x40080000..0x400fffff base peripheral region 2
190
* 0x50000000..0x5fffffff alias of 0x40000000..0x4fffffff
191
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
192
qdev_connect_gpio_out_named(dev_secctl, "nsc_cfg", 0, s->nsc_cfg_in);
193
194
/* The sec_resp_cfg output from the security controller must be split into
195
- * multiple lines, one for each of the PPCs within the IoTKit and one
196
- * that will be an output from the IoTKit to the system.
197
+ * multiple lines, one for each of the PPCs within the ARMSSE and one
198
+ * that will be an output from the ARMSSE to the system.
199
*/
200
object_property_set_int(OBJECT(&s->sec_resp_splitter), 3,
201
"num-lines", &err);
202
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
203
204
/* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */
205
206
- /* 0x40020000 .. 0x4002ffff : IoTKit system control peripheral region */
207
+ /* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
208
/* Devices behind APB PPC1:
209
* 0x4002f000: S32K timer
210
*/
211
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
212
qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 0));
213
sysbus_mmio_map(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, 0x5002e000);
214
215
- /* 0x40080000 .. 0x4008ffff : IoTKit second Base peripheral region */
216
+ /* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */
217
218
qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq);
219
object_property_set_bool(OBJECT(&s->nswatchdog), true, "realized", &err);
220
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
221
* Expose our container region to the board model; this corresponds
222
* to the AHB Slave Expansion ports which allow bus master devices
223
* (eg DMA controllers) in the board model to make transactions into
224
- * devices in the IoTKit.
225
+ * devices in the ARMSSE.
226
*/
227
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
228
229
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
230
static void iotkit_idau_check(IDAUInterface *ii, uint32_t address,
231
int *iregion, bool *exempt, bool *ns, bool *nsc)
232
{
233
- /* For IoTKit systems the IDAU responses are simple logical functions
234
+ /*
235
+ * For ARMSSE systems the IDAU responses are simple logical functions
236
* of the address bits. The NSC attribute is guest-adjustable via the
237
* NSCCFG register in the security controller.
238
*/
239
- IoTKit *s = IOTKIT(ii);
240
+ ARMSSE *s = ARMSSE(ii);
241
int region = extract32(address, 28, 4);
242
243
*ns = !(region & 1);
244
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_vmstate = {
245
.version_id = 1,
246
.minimum_version_id = 1,
247
.fields = (VMStateField[]) {
248
- VMSTATE_UINT32(nsccfg, IoTKit),
249
+ VMSTATE_UINT32(nsccfg, ARMSSE),
250
VMSTATE_END_OF_LIST()
251
}
252
};
253
254
static Property iotkit_properties[] = {
255
- DEFINE_PROP_LINK("memory", IoTKit, board_memory, TYPE_MEMORY_REGION,
256
+ DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
257
MemoryRegion *),
258
- DEFINE_PROP_UINT32("EXP_NUMIRQ", IoTKit, exp_numirq, 64),
259
- DEFINE_PROP_UINT32("MAINCLK", IoTKit, mainclk_frq, 0),
260
+ DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
261
+ DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
262
DEFINE_PROP_END_OF_LIST()
263
};
264
265
static void iotkit_reset(DeviceState *dev)
266
{
267
- IoTKit *s = IOTKIT(dev);
268
+ ARMSSE *s = ARMSSE(dev);
269
270
s->nsccfg = 0;
271
}
63
}
272
@@ -XXX,XX +XXX,XX @@ static void iotkit_class_init(ObjectClass *klass, void *data)
64
273
}
65
static uint64_t ich_hcr_read(CPUARMState *env, const ARMCPRegInfo *ri)
274
275
static const TypeInfo iotkit_info = {
276
- .name = TYPE_IOTKIT,
277
+ .name = TYPE_ARMSSE,
278
.parent = TYPE_SYS_BUS_DEVICE,
279
- .instance_size = sizeof(IoTKit),
280
+ .instance_size = sizeof(ARMSSE),
281
.instance_init = iotkit_init,
282
.class_init = iotkit_class_init,
283
.interfaces = (InterfaceInfo[]) {
284
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
285
index XXXXXXX..XXXXXXX 100644
286
--- a/hw/arm/mps2-tz.c
287
+++ b/hw/arm/mps2-tz.c
288
@@ -XXX,XX +XXX,XX @@ typedef struct {
289
typedef struct {
290
MachineState parent;
291
292
- IoTKit iotkit;
293
+ ARMSSE iotkit;
294
MemoryRegion psram;
295
MemoryRegion ssram[3];
296
MemoryRegion ssram1_m;
297
--
66
--
298
2.20.1
67
2.25.1
299
300
diff view generated by jsdifflib
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
Currently the functions which update the highest priority pending LPI
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.
2
8
3
Instantiates UICR, FICR, FLASH and NVMC in nRF51 SOC.
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.
4
13
5
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Message-id: 20190201023357.22596-3-stefanha@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20220408141550.1271295-28-peter.maydell@linaro.org
11
---
17
---
12
include/hw/arm/nrf51_soc.h | 2 ++
18
hw/intc/arm_gicv3_redist.c | 74 ++++++++++++++++++++++++--------------
13
hw/arm/nrf51_soc.c | 41 +++++++++++++++++++++++++++-----------
19
1 file changed, 47 insertions(+), 27 deletions(-)
14
2 files changed, 31 insertions(+), 12 deletions(-)
15
20
16
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
21
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
17
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/nrf51_soc.h
23
--- a/hw/intc/arm_gicv3_redist.c
19
+++ b/include/hw/arm/nrf51_soc.h
24
+++ b/hw/intc/arm_gicv3_redist.c
20
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ static uint32_t gicr_read_bitmap_reg(GICv3CPUState *cs, MemTxAttrs attrs,
21
#include "hw/char/nrf51_uart.h"
26
return reg;
22
#include "hw/misc/nrf51_rng.h"
27
}
23
#include "hw/gpio/nrf51_gpio.h"
28
24
+#include "hw/nvram/nrf51_nvm.h"
29
+/**
25
#include "hw/timer/nrf51_timer.h"
30
+ * update_for_one_lpi: Update pending information if this LPI is better
26
31
+ *
27
#define TYPE_NRF51_SOC "nrf51-soc"
32
+ * @cs: GICv3CPUState
28
@@ -XXX,XX +XXX,XX @@ typedef struct NRF51State {
33
+ * @irq: interrupt to look up in the LPI Configuration table
29
34
+ * @ctbase: physical address of the LPI Configuration table to use
30
NRF51UARTState uart;
35
+ * @ds: true if priority value should not be shifted
31
NRF51RNGState rng;
36
+ * @hpp: points to pending information to update
32
+ NRF51NVMState nvm;
37
+ *
33
NRF51GPIOState gpio;
38
+ * Look up @irq in the Configuration table specified by @ctbase
34
NRF51TimerState timer[NRF51_NUM_TIMERS];
39
+ * to see if it is enabled and what its priority is. If it is an
35
40
+ * enabled interrupt with a higher priority than that currently
36
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
41
+ * recorded in @hpp, update @hpp.
37
index XXXXXXX..XXXXXXX 100644
42
+ */
38
--- a/hw/arm/nrf51_soc.c
43
+static void update_for_one_lpi(GICv3CPUState *cs, int irq,
39
+++ b/hw/arm/nrf51_soc.c
44
+ uint64_t ctbase, bool ds, PendingIrq *hpp)
40
@@ -XXX,XX +XXX,XX @@
45
+{
41
* are supported in the future, add a sub-class of NRF51SoC for
46
+ uint8_t lpite;
42
* the specific variants
47
+ uint8_t prio;
43
*/
48
+
44
-#define NRF51822_FLASH_SIZE (256 * NRF51_PAGE_SIZE)
49
+ address_space_read(&cs->gic->dma_as,
45
-#define NRF51822_SRAM_SIZE (16 * NRF51_PAGE_SIZE)
50
+ ctbase + ((irq - GICV3_LPI_INTID_START) * sizeof(lpite)),
46
+#define NRF51822_FLASH_PAGES 256
51
+ MEMTXATTRS_UNSPECIFIED, &lpite, sizeof(lpite));
47
+#define NRF51822_SRAM_PAGES 16
52
+
48
+#define NRF51822_FLASH_SIZE (NRF51822_FLASH_PAGES * NRF51_PAGE_SIZE)
53
+ if (!(lpite & LPI_CTE_ENABLED)) {
49
+#define NRF51822_SRAM_SIZE (NRF51822_SRAM_PAGES * NRF51_PAGE_SIZE)
50
51
#define BASE_TO_IRQ(base) ((base >> 12) & 0x1F)
52
53
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
54
55
memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
56
57
- memory_region_init_rom(&s->flash, OBJECT(s), "nrf51.flash", s->flash_size,
58
- &err);
59
- if (err) {
60
- error_propagate(errp, err);
61
- return;
62
- }
63
- memory_region_add_subregion(&s->container, NRF51_FLASH_BASE, &s->flash);
64
-
65
memory_region_init_ram(&s->sram, OBJECT(s), "nrf51.sram", s->sram_size,
66
&err);
67
if (err) {
68
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
69
qdev_get_gpio_in(DEVICE(&s->cpu),
70
BASE_TO_IRQ(NRF51_RNG_BASE)));
71
72
+ /* UICR, FICR, NVMC, FLASH */
73
+ object_property_set_uint(OBJECT(&s->nvm), s->flash_size, "flash-size",
74
+ &err);
75
+ if (err) {
76
+ error_propagate(errp, err);
77
+ return;
54
+ return;
78
+ }
55
+ }
79
+
56
+
80
+ object_property_set_bool(OBJECT(&s->nvm), true, "realized", &err);
57
+ if (ds) {
81
+ if (err) {
58
+ prio = lpite & LPI_PRIORITY_MASK;
82
+ error_propagate(errp, err);
59
+ } else {
83
+ return;
60
+ prio = ((lpite & LPI_PRIORITY_MASK) >> 1) | 0x80;
84
+ }
61
+ }
85
+
62
+
86
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvm), 0);
63
+ if ((prio < hpp->prio) ||
87
+ memory_region_add_subregion_overlap(&s->container, NRF51_NVMC_BASE, mr, 0);
64
+ ((prio == hpp->prio) && (irq <= hpp->irq))) {
88
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvm), 1);
65
+ hpp->irq = irq;
89
+ memory_region_add_subregion_overlap(&s->container, NRF51_FICR_BASE, mr, 0);
66
+ hpp->prio = prio;
90
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvm), 2);
67
+ /* LPIs and vLPIs are always non-secure Grp1 interrupts */
91
+ memory_region_add_subregion_overlap(&s->container, NRF51_UICR_BASE, mr, 0);
68
+ hpp->grp = GICV3_G1NS;
92
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvm), 3);
69
+ }
93
+ memory_region_add_subregion_overlap(&s->container, NRF51_FLASH_BASE, mr, 0);
70
+}
94
+
71
+
95
/* GPIO */
72
static uint8_t gicr_read_ipriorityr(GICv3CPUState *cs, MemTxAttrs attrs,
96
object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
73
int irq)
97
if (err) {
74
{
98
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
75
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
99
76
100
create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE,
77
static void gicv3_redist_check_lpi_priority(GICv3CPUState *cs, int irq)
101
NRF51_IOMEM_SIZE);
78
{
102
- create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE,
79
- AddressSpace *as = &cs->gic->dma_as;
103
- NRF51_FICR_SIZE);
80
- uint64_t lpict_baddr;
104
create_unimplemented_device("nrf51_soc.private",
81
- uint8_t lpite;
105
NRF51_PRIVATE_BASE, NRF51_PRIVATE_SIZE);
82
- uint8_t prio;
83
+ uint64_t lpict_baddr = cs->gicr_propbaser & R_GICR_PROPBASER_PHYADDR_MASK;
84
85
- lpict_baddr = cs->gicr_propbaser & R_GICR_PROPBASER_PHYADDR_MASK;
86
-
87
- address_space_read(as, lpict_baddr + ((irq - GICV3_LPI_INTID_START) *
88
- sizeof(lpite)), MEMTXATTRS_UNSPECIFIED, &lpite,
89
- sizeof(lpite));
90
-
91
- if (!(lpite & LPI_CTE_ENABLED)) {
92
- return;
93
- }
94
-
95
- if (cs->gic->gicd_ctlr & GICD_CTLR_DS) {
96
- prio = lpite & LPI_PRIORITY_MASK;
97
- } else {
98
- prio = ((lpite & LPI_PRIORITY_MASK) >> 1) | 0x80;
99
- }
100
-
101
- if ((prio < cs->hpplpi.prio) ||
102
- ((prio == cs->hpplpi.prio) && (irq <= cs->hpplpi.irq))) {
103
- cs->hpplpi.irq = irq;
104
- cs->hpplpi.prio = prio;
105
- /* LPIs are always non-secure Grp1 interrupts */
106
- cs->hpplpi.grp = GICV3_G1NS;
107
- }
108
+ update_for_one_lpi(cs, irq, lpict_baddr,
109
+ cs->gic->gicd_ctlr & GICD_CTLR_DS,
110
+ &cs->hpplpi);
106
}
111
}
107
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_init(Object *obj)
112
108
sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng),
113
void gicv3_redist_update_lpi_only(GICv3CPUState *cs)
109
TYPE_NRF51_RNG);
110
111
+ sysbus_init_child_obj(obj, "nvm", &s->nvm, sizeof(s->nvm), TYPE_NRF51_NVM);
112
+
113
sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio),
114
TYPE_NRF51_GPIO);
115
116
--
114
--
117
2.20.1
115
2.25.1
118
119
diff view generated by jsdifflib
1
The tcg_register_iommu_notifier() code has a GArray of
1
Factor out the common part of gicv3_redist_update_lpi_only() into
2
TCGIOMMUNotifier structs which it has registered by passing
2
a new function update_for_all_lpis(), which does a full rescan
3
memory_region_register_iommu_notifier() a pointer to the embedded
3
of an LPI Pending table and sets the specified PendingIrq struct
4
IOMMUNotifier field. Unfortunately, if we need to enlarge the
4
with the highest priority pending enabled LPI it finds.
5
array via g_array_set_size() this can cause a realloc(), which
6
invalidates the pointer that memory_region_register_iommu_notifier()
7
put into the MemoryRegion's iommu_notify list. This can result
8
in segfaults.
9
5
10
Switch the GArray to holding pointers to the TCGIOMMUNotifier
11
structs, so that we can individually allocate and free them.
12
13
Cc: qemu-stable@nongnu.org
14
Fixes: 1f871c5e6b0f30644a60a ("exec.c: Handle IOMMUs in address_space_translate_for_iotlb()")
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20190128174241.5860-1-peter.maydell@linaro.org
8
Message-id: 20220408141550.1271295-29-peter.maydell@linaro.org
18
---
9
---
19
exec.c | 10 ++++++----
10
hw/intc/arm_gicv3_redist.c | 66 ++++++++++++++++++++++++++------------
20
1 file changed, 6 insertions(+), 4 deletions(-)
11
1 file changed, 46 insertions(+), 20 deletions(-)
21
12
22
diff --git a/exec.c b/exec.c
13
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
23
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
24
--- a/exec.c
15
--- a/hw/intc/arm_gicv3_redist.c
25
+++ b/exec.c
16
+++ b/hw/intc/arm_gicv3_redist.c
26
@@ -XXX,XX +XXX,XX @@ static void tcg_register_iommu_notifier(CPUState *cpu,
17
@@ -XXX,XX +XXX,XX @@ static void update_for_one_lpi(GICv3CPUState *cs, int irq,
27
int i;
28
29
for (i = 0; i < cpu->iommu_notifiers->len; i++) {
30
- notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
31
+ notifier = g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i);
32
if (notifier->mr == mr && notifier->iommu_idx == iommu_idx) {
33
break;
34
}
35
@@ -XXX,XX +XXX,XX @@ static void tcg_register_iommu_notifier(CPUState *cpu,
36
if (i == cpu->iommu_notifiers->len) {
37
/* Not found, add a new entry at the end of the array */
38
cpu->iommu_notifiers = g_array_set_size(cpu->iommu_notifiers, i + 1);
39
- notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
40
+ notifier = g_new0(TCGIOMMUNotifier, 1);
41
+ g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i) = notifier;
42
43
notifier->mr = mr;
44
notifier->iommu_idx = iommu_idx;
45
@@ -XXX,XX +XXX,XX @@ static void tcg_iommu_free_notifier_list(CPUState *cpu)
46
TCGIOMMUNotifier *notifier;
47
48
for (i = 0; i < cpu->iommu_notifiers->len; i++) {
49
- notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
50
+ notifier = g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i);
51
memory_region_unregister_iommu_notifier(notifier->mr, &notifier->n);
52
+ g_free(notifier);
53
}
18
}
54
g_array_free(cpu->iommu_notifiers, true);
55
}
19
}
56
@@ -XXX,XX +XXX,XX @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
20
57
vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu);
21
+/**
22
+ * update_for_all_lpis: Fully scan LPI tables and find best pending LPI
23
+ *
24
+ * @cs: GICv3CPUState
25
+ * @ptbase: physical address of LPI Pending table
26
+ * @ctbase: physical address of LPI Configuration table
27
+ * @ptsizebits: size of tables, specified as number of interrupt ID bits minus 1
28
+ * @ds: true if priority value should not be shifted
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
{
66
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_update_lpi_only(GICv3CPUState *cs)
67
* priority is lower than the last computed high priority lpi interrupt.
68
* If yes, replace current LPI as the new high priority lpi interrupt.
69
*/
70
- AddressSpace *as = &cs->gic->dma_as;
71
- uint64_t lpipt_baddr;
72
- uint32_t pendt_size = 0;
73
- uint8_t pend;
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;
58
}
81
}
59
82
60
- cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier));
83
- cs->hpplpi.prio = 0xff;
61
+ cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier *));
84
-
62
#endif
85
lpipt_baddr = cs->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK;
86
+ lpict_baddr = cs->gicr_propbaser & R_GICR_PROPBASER_PHYADDR_MASK;
87
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
- }
101
+ update_for_all_lpis(cs, lpipt_baddr, lpict_baddr, idbits,
102
+ cs->gic->gicd_ctlr & GICD_CTLR_DS, &cs->hpplpi);
63
}
103
}
64
104
105
void gicv3_redist_update_lpi(GICv3CPUState *cs)
65
--
106
--
66
2.20.1
107
2.25.1
67
68
diff view generated by jsdifflib
1
In the encoding groups
1
The guest uses GICR_VPENDBASER to tell the redistributor when it is
2
* floating-point data-processing (1 source)
2
scheduling or descheduling a vCPU. When it writes and changes the
3
* floating-point data-processing (2 source)
3
VALID bit from 0 to 1, it is scheduling a vCPU, and we must update
4
* floating-point data-processing (3 source)
4
our view of the current highest priority pending vLPI from the new
5
* floating-point immediate
5
Pending and Configuration tables. When it writes and changes the
6
* floating-point compare
6
VALID bit from 1 to 0, it is descheduling, which means that there is
7
* floating-ponit conditional compare
7
no longer a highest priority pending vLPI.
8
* floating-point conditional select
9
8
10
bit 31 is M and bit 29 is S (and bit 30 is 0, already checked at
9
The specification allows the implementation to use part of the vLPI
11
this point in the decode). None of these groups allocate any
10
Pending table as an IMPDEF area where it can cache information when a
12
encoding for M=1 or S=1. We checked this in disas_fp_compare(),
11
vCPU is descheduled, so that it can avoid having to do a full rescan
13
disas_fp_ccomp() and disas_fp_csel(), but missed it in disas_fp_1src(),
12
of the tables when the vCPU is scheduled again. For now, we don't
14
disas_fp_2src(), disas_fp_3src() and disas_fp_imm().
13
take advantage of this, and simply do a complete rescan.
15
14
16
We also missed that in the fp immediate encoding the imm5 field
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
must be all zeroes.
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20220408141550.1271295-30-peter.maydell@linaro.org
18
---
19
hw/intc/arm_gicv3_redist.c | 87 ++++++++++++++++++++++++++++++++++++--
20
1 file changed, 84 insertions(+), 3 deletions(-)
18
21
19
Correctly UNDEF the unallocated encodings here.
22
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
20
21
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
24
Message-id: 20190125182626.9221-7-peter.maydell@linaro.org
25
---
26
target/arm/translate-a64.c | 22 +++++++++++++++++++++-
27
1 file changed, 21 insertions(+), 1 deletion(-)
28
29
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
30
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/translate-a64.c
24
--- a/hw/intc/arm_gicv3_redist.c
32
+++ b/target/arm/translate-a64.c
25
+++ b/hw/intc/arm_gicv3_redist.c
33
@@ -XXX,XX +XXX,XX @@ static void handle_fp_fcvt(DisasContext *s, int opcode,
26
@@ -XXX,XX +XXX,XX @@ static void gicr_write_ipriorityr(GICv3CPUState *cs, MemTxAttrs attrs, int irq,
34
*/
27
cs->gicr_ipriorityr[irq] = value;
35
static void disas_fp_1src(DisasContext *s, uint32_t insn)
28
}
36
{
29
37
+ int mos = extract32(insn, 29, 3);
30
+static void gicv3_redist_update_vlpi_only(GICv3CPUState *cs)
38
int type = extract32(insn, 22, 2);
31
+{
39
int opcode = extract32(insn, 15, 6);
32
+ uint64_t ptbase, ctbase, idbits;
40
int rn = extract32(insn, 5, 5);
33
+
41
int rd = extract32(insn, 0, 5);
34
+ if (!FIELD_EX64(cs->gicr_vpendbaser, GICR_VPENDBASER, VALID)) {
42
35
+ cs->hppvlpi.prio = 0xff;
43
+ if (mos) {
44
+ unallocated_encoding(s);
45
+ return;
36
+ return;
46
+ }
37
+ }
47
+
38
+
48
switch (opcode) {
39
+ ptbase = cs->gicr_vpendbaser & R_GICR_VPENDBASER_PHYADDR_MASK;
49
case 0x4: case 0x5: case 0x7:
40
+ ctbase = cs->gicr_vpropbaser & R_GICR_VPROPBASER_PHYADDR_MASK;
50
{
41
+ idbits = FIELD_EX64(cs->gicr_vpropbaser, GICR_VPROPBASER, IDBITS);
51
@@ -XXX,XX +XXX,XX @@ static void handle_fp_2src_half(DisasContext *s, int opcode,
42
+
52
*/
43
+ update_for_all_lpis(cs, ptbase, ctbase, idbits, true, &cs->hppvlpi);
53
static void disas_fp_2src(DisasContext *s, uint32_t insn)
44
+}
54
{
45
+
55
+ int mos = extract32(insn, 29, 3);
46
+static void gicv3_redist_update_vlpi(GICv3CPUState *cs)
56
int type = extract32(insn, 22, 2);
47
+{
57
int rd = extract32(insn, 0, 5);
48
+ gicv3_redist_update_vlpi_only(cs);
58
int rn = extract32(insn, 5, 5);
49
+ gicv3_cpuif_virt_irq_fiq_update(cs);
59
int rm = extract32(insn, 16, 5);
50
+}
60
int opcode = extract32(insn, 12, 4);
51
+
61
52
+static void gicr_write_vpendbaser(GICv3CPUState *cs, uint64_t newval)
62
- if (opcode > 8) {
53
+{
63
+ if (opcode > 8 || mos) {
54
+ /* Write @newval to GICR_VPENDBASER, handling its effects */
64
unallocated_encoding(s);
55
+ bool oldvalid = FIELD_EX64(cs->gicr_vpendbaser, GICR_VPENDBASER, VALID);
65
return;
56
+ bool newvalid = FIELD_EX64(newval, GICR_VPENDBASER, VALID);
66
}
57
+ bool pendinglast;
67
@@ -XXX,XX +XXX,XX @@ static void handle_fp_3src_half(DisasContext *s, bool o0, bool o1,
58
+
68
*/
59
+ /*
69
static void disas_fp_3src(DisasContext *s, uint32_t insn)
60
+ * The DIRTY bit is read-only and for us is always zero;
70
{
61
+ * other fields are writeable.
71
+ int mos = extract32(insn, 29, 3);
62
+ */
72
int type = extract32(insn, 22, 2);
63
+ newval &= R_GICR_VPENDBASER_INNERCACHE_MASK |
73
int rd = extract32(insn, 0, 5);
64
+ R_GICR_VPENDBASER_SHAREABILITY_MASK |
74
int rn = extract32(insn, 5, 5);
65
+ R_GICR_VPENDBASER_PHYADDR_MASK |
75
@@ -XXX,XX +XXX,XX @@ static void disas_fp_3src(DisasContext *s, uint32_t insn)
66
+ R_GICR_VPENDBASER_OUTERCACHE_MASK |
76
bool o0 = extract32(insn, 15, 1);
67
+ R_GICR_VPENDBASER_PENDINGLAST_MASK |
77
bool o1 = extract32(insn, 21, 1);
68
+ R_GICR_VPENDBASER_IDAI_MASK |
78
69
+ R_GICR_VPENDBASER_VALID_MASK;
79
+ if (mos) {
70
+
80
+ unallocated_encoding(s);
71
+ if (oldvalid && newvalid) {
72
+ /*
73
+ * Changing other fields while VALID is 1 is UNPREDICTABLE;
74
+ * we choose to log and ignore the write.
75
+ */
76
+ if (cs->gicr_vpendbaser ^ newval) {
77
+ qemu_log_mask(LOG_GUEST_ERROR,
78
+ "%s: Changing GICR_VPENDBASER when VALID=1 "
79
+ "is UNPREDICTABLE\n", __func__);
80
+ }
81
+ return;
82
+ }
83
+ if (!oldvalid && !newvalid) {
84
+ cs->gicr_vpendbaser = newval;
81
+ return;
85
+ return;
82
+ }
86
+ }
83
+
87
+
84
switch (type) {
88
+ if (newvalid) {
85
case 0:
89
+ /*
86
if (!fp_access_check(s)) {
90
+ * Valid going from 0 to 1: update hppvlpi from tables.
87
@@ -XXX,XX +XXX,XX @@ uint64_t vfp_expand_imm(int size, uint8_t imm8)
91
+ * If IDAI is 0 we are allowed to use the info we cached in
88
static void disas_fp_imm(DisasContext *s, uint32_t insn)
92
+ * the IMPDEF area of the table.
89
{
93
+ * PendingLast is RES1 when we make this transition.
90
int rd = extract32(insn, 0, 5);
94
+ */
91
+ int imm5 = extract32(insn, 5, 5);
95
+ pendinglast = true;
92
int imm8 = extract32(insn, 13, 8);
96
+ } else {
93
int type = extract32(insn, 22, 2);
97
+ /*
94
+ int mos = extract32(insn, 29, 3);
98
+ * Valid going from 1 to 0:
95
uint64_t imm;
99
+ * Set PendingLast if there was a pending enabled interrupt
96
TCGv_i64 tcg_res;
100
+ * for the vPE that was just descheduled.
97
TCGMemOp sz;
101
+ * If we cache info in the IMPDEF area, write it out here.
98
102
+ */
99
+ if (mos || imm5) {
103
+ pendinglast = cs->hppvlpi.prio != 0xff;
100
+ unallocated_encoding(s);
101
+ return;
102
+ }
104
+ }
103
+
105
+
104
switch (type) {
106
+ newval = FIELD_DP64(newval, GICR_VPENDBASER, PENDINGLAST, pendinglast);
105
case 0:
107
+ cs->gicr_vpendbaser = newval;
106
sz = MO_32;
108
+ gicv3_redist_update_vlpi(cs);
109
+}
110
+
111
static MemTxResult gicr_readb(GICv3CPUState *cs, hwaddr offset,
112
uint64_t *data, MemTxAttrs attrs)
113
{
114
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset,
115
cs->gicr_vpropbaser = deposit64(cs->gicr_vpropbaser, 32, 32, value);
116
return MEMTX_OK;
117
case GICR_VPENDBASER:
118
- cs->gicr_vpendbaser = deposit64(cs->gicr_vpendbaser, 0, 32, value);
119
+ gicr_write_vpendbaser(cs, deposit64(cs->gicr_vpendbaser, 0, 32, value));
120
return MEMTX_OK;
121
case GICR_VPENDBASER + 4:
122
- cs->gicr_vpendbaser = deposit64(cs->gicr_vpendbaser, 32, 32, value);
123
+ gicr_write_vpendbaser(cs, deposit64(cs->gicr_vpendbaser, 32, 32, value));
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;
107
--
136
--
108
2.20.1
137
2.25.1
109
110
diff view generated by jsdifflib
1
Add unimplemented-device stubs for the various Power Policy Unit
1
Factor out the code which sets a single bit in an LPI pending table.
2
devices that the SSE-200 has.
2
We're going to need this for handling vLPI tables, not just the
3
physical LPI table.
3
4
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20190121185118.18550-17-peter.maydell@linaro.org
7
Message-id: 20220408141550.1271295-31-peter.maydell@linaro.org
7
---
8
---
8
include/hw/arm/armsse.h | 11 ++++++++
9
hw/intc/arm_gicv3_redist.c | 49 +++++++++++++++++++++++---------------
9
hw/arm/armsse.c | 58 +++++++++++++++++++++++++++++++++++++++++
10
1 file changed, 30 insertions(+), 19 deletions(-)
10
2 files changed, 69 insertions(+)
11
11
12
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
12
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/armsse.h
14
--- a/hw/intc/arm_gicv3_redist.c
15
+++ b/include/hw/arm/armsse.h
15
+++ b/hw/intc/arm_gicv3_redist.c
16
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ static void update_for_all_lpis(GICv3CPUState *cs, uint64_t ptbase,
17
18
#define SSE_MAX_CPUS 2
19
20
+/* These define what each PPU in the ppu[] index is for */
21
+#define CPU0CORE_PPU 0
22
+#define CPU1CORE_PPU 1
23
+#define DBG_PPU 2
24
+#define RAM0_PPU 3
25
+#define RAM1_PPU 4
26
+#define RAM2_PPU 5
27
+#define RAM3_PPU 6
28
+#define NUM_PPUS 7
29
+
30
typedef struct ARMSSE {
31
/*< private >*/
32
SysBusDevice parent_obj;
33
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
34
IoTKitSysCtl sysinfo;
35
36
UnimplementedDeviceState mhu[2];
37
+ UnimplementedDeviceState ppu[NUM_PPUS];
38
39
/*
40
* 'container' holds all devices seen by all CPUs.
41
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/arm/armsse.c
44
+++ b/hw/arm/armsse.c
45
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
46
uint32_t sys_version;
47
SysConfigFormat sys_config_format;
48
bool has_mhus;
49
+ bool has_ppus;
50
};
51
52
static const ARMSSEInfo armsse_variants[] = {
53
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
54
.sys_version = 0x41743,
55
.sys_config_format = IoTKitFormat,
56
.has_mhus = false,
57
+ .has_ppus = false,
58
},
59
};
60
61
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
62
sysbus_init_child_obj(obj, "mhu1", &s->mhu[1], sizeof(s->mhu[1]),
63
TYPE_UNIMPLEMENTED_DEVICE);
64
}
65
+ if (info->has_ppus) {
66
+ for (i = 0; i < info->num_cpus; i++) {
67
+ char *name = g_strdup_printf("CPU%dCORE_PPU", i);
68
+ int ppuidx = CPU0CORE_PPU + i;
69
+
70
+ sysbus_init_child_obj(obj, name, &s->ppu[ppuidx],
71
+ sizeof(s->ppu[ppuidx]),
72
+ TYPE_UNIMPLEMENTED_DEVICE);
73
+ g_free(name);
74
+ }
75
+ sysbus_init_child_obj(obj, "DBG_PPU", &s->ppu[DBG_PPU],
76
+ sizeof(s->ppu[DBG_PPU]),
77
+ TYPE_UNIMPLEMENTED_DEVICE);
78
+ for (i = 0; i < info->sram_banks; i++) {
79
+ char *name = g_strdup_printf("RAM%d_PPU", i);
80
+ int ppuidx = RAM0_PPU + i;
81
+
82
+ sysbus_init_child_obj(obj, name, &s->ppu[ppuidx],
83
+ sizeof(s->ppu[ppuidx]),
84
+ TYPE_UNIMPLEMENTED_DEVICE);
85
+ g_free(name);
86
+ }
87
+ }
88
object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
89
sizeof(s->nmi_orgate), TYPE_OR_IRQ,
90
&error_abort, NULL);
91
@@ -XXX,XX +XXX,XX @@ static qemu_irq armsse_get_common_irq_in(ARMSSE *s, int irqno)
92
}
17
}
93
}
18
}
94
19
95
+static void map_ppu(ARMSSE *s, int ppuidx, const char *name, hwaddr addr)
20
+/**
21
+ * set_lpi_pending_bit: Set or clear pending bit for an LPI
22
+ *
23
+ * @cs: GICv3CPUState
24
+ * @ptbase: physical address of LPI Pending table
25
+ * @irq: LPI to change pending state for
26
+ * @level: false to clear pending state, true to set
27
+ *
28
+ * Returns true if we needed to do something, false if the pending bit
29
+ * was already at @level.
30
+ */
31
+static bool set_pending_table_bit(GICv3CPUState *cs, uint64_t ptbase,
32
+ int irq, bool level)
96
+{
33
+{
97
+ /* Map a PPU unimplemented device stub */
34
+ AddressSpace *as = &cs->gic->dma_as;
98
+ DeviceState *dev = DEVICE(&s->ppu[ppuidx]);
35
+ uint64_t addr = ptbase + irq / 8;
36
+ uint8_t pend;
99
+
37
+
100
+ qdev_prop_set_string(dev, "name", name);
38
+ address_space_read(as, addr, MEMTXATTRS_UNSPECIFIED, &pend, 1);
101
+ qdev_prop_set_uint64(dev, "size", 0x1000);
39
+ if (extract32(pend, irq % 8, 1) == level) {
102
+ qdev_init_nofail(dev);
40
+ /* Bit already at requested state, no action required */
103
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ppu[ppuidx]), 0, addr);
41
+ return false;
42
+ }
43
+ pend = deposit32(pend, irq % 8, 1, level ? 1 : 0);
44
+ address_space_write(as, addr, MEMTXATTRS_UNSPECIFIED, &pend, 1);
45
+ return true;
104
+}
46
+}
105
+
47
+
106
static void armsse_realize(DeviceState *dev, Error **errp)
48
static uint8_t gicr_read_ipriorityr(GICv3CPUState *cs, MemTxAttrs attrs,
49
int irq)
107
{
50
{
108
ARMSSE *s = ARMSSE(dev);
51
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level)
109
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
52
* This function updates the pending bit in lpi pending table for
53
* the irq being activated or deactivated.
54
*/
55
- AddressSpace *as = &cs->gic->dma_as;
56
uint64_t lpipt_baddr;
57
- bool ispend = false;
58
- uint8_t pend;
59
60
- /*
61
- * get the bit value corresponding to this irq in the
62
- * lpi pending table
63
- */
64
lpipt_baddr = cs->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK;
65
-
66
- address_space_read(as, lpipt_baddr + ((irq / 8) * sizeof(pend)),
67
- MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend));
68
-
69
- ispend = extract32(pend, irq % 8, 1);
70
-
71
- /* no change in the value of pending bit, return */
72
- if (ispend == level) {
73
+ if (!set_pending_table_bit(cs, lpipt_baddr, irq, level)) {
74
+ /* no change in the value of pending bit, return */
75
return;
110
}
76
}
111
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctl), 0, 0x50021000);
77
- pend = deposit32(pend, irq % 8, 1, level ? 1 : 0);
112
78
-
113
+ if (info->has_ppus) {
79
- address_space_write(as, lpipt_baddr + ((irq / 8) * sizeof(pend)),
114
+ /* CPUnCORE_PPU for each CPU */
80
- MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend));
115
+ for (i = 0; i < info->num_cpus; i++) {
81
116
+ char *name = g_strdup_printf("CPU%dCORE_PPU", i);
82
/*
117
+
83
* check if this LPI is better than the current hpplpi, if yes
118
+ map_ppu(s, CPU0CORE_PPU + i, name, 0x50023000 + i * 0x2000);
119
+ /*
120
+ * We don't support CPU debug so don't create the
121
+ * CPU0DEBUG_PPU at 0x50024000 and 0x50026000.
122
+ */
123
+ g_free(name);
124
+ }
125
+ map_ppu(s, DBG_PPU, "DBG_PPU", 0x50029000);
126
+
127
+ for (i = 0; i < info->sram_banks; i++) {
128
+ char *name = g_strdup_printf("RAM%d_PPU", i);
129
+
130
+ map_ppu(s, RAM0_PPU + i, name, 0x5002a000 + i * 0x1000);
131
+ g_free(name);
132
+ }
133
+ }
134
+
135
/* This OR gate wires together outputs from the secure watchdogs to NMI */
136
object_property_set_int(OBJECT(&s->nmi_orgate), 2, "num-lines", &err);
137
if (err) {
138
--
84
--
139
2.20.1
85
2.25.1
140
141
diff view generated by jsdifflib
1
The SSE-200 has a "CPU local security control" register bank; add an
1
Implement the function gicv3_redist_process_vlpi(), which was left as
2
unimplemented-device stub for it. (The register bank has only one
2
just a stub earlier. This function deals with being handed a VLPI by
3
interesting register, which allows the guest to lock down changes
3
the ITS. It must set the bit in the pending table. If the vCPU is
4
to various CPU registers so they cannot be modified further. We
4
currently resident we must recalculate the highest priority pending
5
don't support that in our Cortex-M33 model anyway.)
5
vLPI; otherwise we may need to ring a "doorbell" interrupt to let the
6
hypervisor know it might want to reschedule the vCPU.
6
7
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20190121185118.18550-19-peter.maydell@linaro.org
10
Message-id: 20220408141550.1271295-32-peter.maydell@linaro.org
10
---
11
---
11
include/hw/arm/armsse.h | 1 +
12
hw/intc/arm_gicv3_redist.c | 48 ++++++++++++++++++++++++++++++++++----
12
hw/arm/armsse.c | 31 +++++++++++++++++++++++++++++++
13
1 file changed, 44 insertions(+), 4 deletions(-)
13
2 files changed, 32 insertions(+)
14
14
15
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
15
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/armsse.h
17
--- a/hw/intc/arm_gicv3_redist.c
18
+++ b/include/hw/arm/armsse.h
18
+++ b/hw/intc/arm_gicv3_redist.c
19
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
19
@@ -XXX,XX +XXX,XX @@ static uint32_t gicr_read_bitmap_reg(GICv3CPUState *cs, MemTxAttrs attrs,
20
UnimplementedDeviceState mhu[2];
20
return reg;
21
UnimplementedDeviceState ppu[NUM_PPUS];
21
}
22
UnimplementedDeviceState cachectrl[SSE_MAX_CPUS];
22
23
+ UnimplementedDeviceState cpusecctrl[SSE_MAX_CPUS];
23
+static bool vcpu_resident(GICv3CPUState *cs, uint64_t vptaddr)
24
24
+{
25
/*
25
+ /*
26
* 'container' holds all devices seen by all CPUs.
26
+ * Return true if a vCPU is resident, which is defined by
27
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
27
+ * whether the GICR_VPENDBASER register is marked VALID and
28
index XXXXXXX..XXXXXXX 100644
28
+ * has the right virtual pending table address.
29
--- a/hw/arm/armsse.c
29
+ */
30
+++ b/hw/arm/armsse.c
30
+ if (!FIELD_EX64(cs->gicr_vpendbaser, GICR_VPENDBASER, VALID)) {
31
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
31
+ return false;
32
bool has_mhus;
32
+ }
33
bool has_ppus;
33
+ return vptaddr == (cs->gicr_vpendbaser & R_GICR_VPENDBASER_PHYADDR_MASK);
34
bool has_cachectrl;
34
+}
35
+ bool has_cpusecctrl;
36
};
37
38
static const ARMSSEInfo armsse_variants[] = {
39
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
40
.has_mhus = false,
41
.has_ppus = false,
42
.has_cachectrl = false,
43
+ .has_cpusecctrl = false,
44
},
45
};
46
47
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
48
g_free(name);
49
}
50
}
51
+ if (info->has_cpusecctrl) {
52
+ for (i = 0; i < info->num_cpus; i++) {
53
+ char *name = g_strdup_printf("cpusecctrl%d", i);
54
+
35
+
55
+ sysbus_init_child_obj(obj, name, &s->cpusecctrl[i],
36
/**
56
+ sizeof(s->cpusecctrl[i]),
37
* update_for_one_lpi: Update pending information if this LPI is better
57
+ TYPE_UNIMPLEMENTED_DEVICE);
38
*
58
+ g_free(name);
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
+
51
+ if (resident) {
52
+ uint32_t idbits = FIELD_EX64(cs->gicr_vpropbaser, GICR_VPROPBASER, IDBITS);
53
+ if (irq >= (1ULL << (idbits + 1))) {
54
+ return;
59
+ }
55
+ }
60
+ }
56
+ }
61
object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
62
sizeof(s->nmi_orgate), TYPE_OR_IRQ,
63
&error_abort, NULL);
64
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
65
memory_region_add_subregion(&s->cpu_container[i], 0x50010000, mr);
66
}
67
}
68
+ if (info->has_cpusecctrl) {
69
+ for (i = 0; i < info->num_cpus; i++) {
70
+ char *name = g_strdup_printf("CPUSECCTRL%d", i);
71
+ MemoryRegion *mr;
72
+
57
+
73
+ qdev_prop_set_string(DEVICE(&s->cpusecctrl[i]), "name", name);
58
+ bit_changed = set_pending_table_bit(cs, vptaddr, irq, level);
74
+ g_free(name);
59
+ if (resident && bit_changed) {
75
+ qdev_prop_set_uint64(DEVICE(&s->cpusecctrl[i]), "size", 0x1000);
60
+ if (level) {
76
+ object_property_set_bool(OBJECT(&s->cpusecctrl[i]), true,
61
+ /* Check whether this vLPI is now the best */
77
+ "realized", &err);
62
+ ctbase = cs->gicr_vpropbaser & R_GICR_VPROPBASER_PHYADDR_MASK;
78
+ if (err) {
63
+ update_for_one_lpi(cs, irq, ctbase, true, &cs->hppvlpi);
79
+ error_propagate(errp, err);
64
+ gicv3_cpuif_virt_irq_fiq_update(cs);
80
+ return;
65
+ } else {
66
+ /* Only need to recalculate if this was previously the best vLPI */
67
+ if (irq == cs->hppvlpi.irq) {
68
+ gicv3_redist_update_vlpi(cs);
81
+ }
69
+ }
82
+
83
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpusecctrl[i]), 0);
84
+ memory_region_add_subregion(&s->cpu_container[i], 0x50011000, mr);
85
+ }
70
+ }
86
+ }
71
+ }
87
72
+
88
/* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
73
+ if (!resident && level && doorbell != INTID_SPURIOUS &&
89
/* Devices behind APB PPC1:
74
+ (cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS)) {
75
+ /* vCPU is not currently resident: ring the doorbell */
76
+ gicv3_redist_process_lpi(cs, doorbell, 1);
77
+ }
78
}
79
80
void gicv3_redist_mov_vlpi(GICv3CPUState *src, uint64_t src_vptaddr,
90
--
81
--
91
2.20.1
82
2.25.1
92
93
diff view generated by jsdifflib
1
The SSE-200 gives each CPU a register bank to use to control its
1
Implement the function gicv3_redist_vlpi_pending(), which was
2
L1 instruction cache. Put in an unimplemented-device stub for this.
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.
3
7
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20190121185118.18550-18-peter.maydell@linaro.org
10
Message-id: 20220408141550.1271295-33-peter.maydell@linaro.org
7
---
11
---
8
include/hw/arm/armsse.h | 1 +
12
hw/intc/arm_gicv3_redist.c | 23 +++++++++++++++++++++--
9
hw/arm/armsse.c | 39 ++++++++++++++++++++++++++++++++++++++-
13
1 file changed, 21 insertions(+), 2 deletions(-)
10
2 files changed, 39 insertions(+), 1 deletion(-)
11
14
12
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
15
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/armsse.h
17
--- a/hw/intc/arm_gicv3_redist.c
15
+++ b/include/hw/arm/armsse.h
18
+++ b/hw/intc/arm_gicv3_redist.c
16
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
19
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_movall_lpis(GICv3CPUState *src, GICv3CPUState *dest)
17
20
void gicv3_redist_vlpi_pending(GICv3CPUState *cs, int irq, int level)
18
UnimplementedDeviceState mhu[2];
21
{
19
UnimplementedDeviceState ppu[NUM_PPUS];
20
+ UnimplementedDeviceState cachectrl[SSE_MAX_CPUS];
21
22
/*
22
/*
23
* 'container' holds all devices seen by all CPUs.
23
- * The redistributor handling for changing the pending state
24
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
24
- * of a vLPI will be added in a subsequent commit.
25
index XXXXXXX..XXXXXXX 100644
25
+ * Change the pending state of the specified vLPI.
26
--- a/hw/arm/armsse.c
26
+ * Unlike gicv3_redist_process_vlpi(), we know here that the
27
+++ b/hw/arm/armsse.c
27
+ * vCPU is definitely resident on this redistributor, and that
28
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
28
+ * the irq is in range.
29
SysConfigFormat sys_config_format;
29
*/
30
bool has_mhus;
30
+ uint64_t vptbase, ctbase;
31
bool has_ppus;
32
+ bool has_cachectrl;
33
};
34
35
static const ARMSSEInfo armsse_variants[] = {
36
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
37
.sys_config_format = IoTKitFormat,
38
.has_mhus = false,
39
.has_ppus = false,
40
+ .has_cachectrl = false,
41
},
42
};
43
44
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
45
g_free(name);
46
}
47
}
48
+ if (info->has_cachectrl) {
49
+ for (i = 0; i < info->num_cpus; i++) {
50
+ char *name = g_strdup_printf("cachectrl%d", i);
51
+
31
+
52
+ sysbus_init_child_obj(obj, name, &s->cachectrl[i],
32
+ vptbase = FIELD_EX64(cs->gicr_vpendbaser, GICR_VPENDBASER, PHYADDR) << 16;
53
+ sizeof(s->cachectrl[i]),
33
+
54
+ TYPE_UNIMPLEMENTED_DEVICE);
34
+ if (set_pending_table_bit(cs, vptbase, irq, level)) {
55
+ g_free(name);
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
+ }
56
+ }
45
+ }
57
+ }
46
+ }
58
object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
47
}
59
sizeof(s->nmi_orgate), TYPE_OR_IRQ,
48
60
&error_abort, NULL);
49
void gicv3_redist_process_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr,
61
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
62
qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
63
armsse_get_common_irq_in(s, 10));
64
65
- /* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */
66
+ /*
67
+ * 0x40010000 .. 0x4001ffff (and the 0x5001000... secure-only alias):
68
+ * private per-CPU region (all these devices are SSE-200 only):
69
+ * 0x50010000: L1 icache control registers
70
+ * 0x50011000: CPUSECCTRL (CPU local security control registers)
71
+ * 0x4001f000 and 0x5001f000: CPU_IDENTITY register block
72
+ */
73
+ if (info->has_cachectrl) {
74
+ for (i = 0; i < info->num_cpus; i++) {
75
+ char *name = g_strdup_printf("cachectrl%d", i);
76
+ MemoryRegion *mr;
77
+
78
+ qdev_prop_set_string(DEVICE(&s->cachectrl[i]), "name", name);
79
+ g_free(name);
80
+ qdev_prop_set_uint64(DEVICE(&s->cachectrl[i]), "size", 0x1000);
81
+ object_property_set_bool(OBJECT(&s->cachectrl[i]), true,
82
+ "realized", &err);
83
+ if (err) {
84
+ error_propagate(errp, err);
85
+ return;
86
+ }
87
+
88
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cachectrl[i]), 0);
89
+ memory_region_add_subregion(&s->cpu_container[i], 0x50010000, mr);
90
+ }
91
+ }
92
93
/* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
94
/* Devices behind APB PPC1:
95
--
50
--
96
2.20.1
51
2.25.1
97
98
diff view generated by jsdifflib
1
Create a cluster object to hold each CPU in the SSE. They are
1
We can use our new set_pending_table_bit() utility function
2
logically distinct and may be configured differently (for instance
2
in gicv3_redist_mov_lpi() to clear the bit in the source
3
one may not have an FPU where the other does).
3
pending table, rather than doing the "load, clear bit, store"
4
ourselves.
4
5
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20190121185118.18550-14-peter.maydell@linaro.org
8
Message-id: 20220408141550.1271295-34-peter.maydell@linaro.org
8
---
9
---
9
include/hw/arm/armsse.h | 2 ++
10
hw/intc/arm_gicv3_redist.c | 9 +--------
10
hw/arm/armsse.c | 31 ++++++++++++++++++++++++++++---
11
1 file changed, 1 insertion(+), 8 deletions(-)
11
2 files changed, 30 insertions(+), 3 deletions(-)
12
12
13
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
13
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/arm/armsse.h
15
--- a/hw/intc/arm_gicv3_redist.c
16
+++ b/include/hw/arm/armsse.h
16
+++ b/hw/intc/arm_gicv3_redist.c
17
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_mov_lpi(GICv3CPUState *src, GICv3CPUState *dest, int irq)
18
#include "hw/misc/iotkit-sysinfo.h"
18
* we choose to NOP. If LPIs are disabled on source there's nothing
19
#include "hw/or-irq.h"
19
* to be transferred anyway.
20
#include "hw/core/split-irq.h"
20
*/
21
+#include "hw/cpu/cluster.h"
21
- AddressSpace *as = &src->gic->dma_as;
22
22
uint64_t idbits;
23
#define TYPE_ARMSSE "arm-sse"
23
uint32_t pendt_size;
24
#define ARMSSE(obj) OBJECT_CHECK(ARMSSE, (obj), TYPE_ARMSSE)
24
uint64_t src_baddr;
25
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
25
- uint8_t src_pend;
26
26
27
/*< public >*/
27
if (!(src->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) ||
28
ARMv7MState armv7m[SSE_MAX_CPUS];
28
!(dest->gicr_ctlr & GICR_CTLR_ENABLE_LPIS)) {
29
+ CPUClusterState cluster[SSE_MAX_CPUS];
29
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_mov_lpi(GICv3CPUState *src, GICv3CPUState *dest, int irq)
30
IoTKitSecCtl secctl;
30
31
TZPPC apb_ppc0;
31
src_baddr = src->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK;
32
TZPPC apb_ppc1;
32
33
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
33
- address_space_read(as, src_baddr + (irq / 8),
34
index XXXXXXX..XXXXXXX 100644
34
- MEMTXATTRS_UNSPECIFIED, &src_pend, sizeof(src_pend));
35
--- a/hw/arm/armsse.c
35
- if (!extract32(src_pend, irq % 8, 1)) {
36
+++ b/hw/arm/armsse.c
36
+ if (!set_pending_table_bit(src, src_baddr, irq, 0)) {
37
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
37
/* Not pending on source, nothing to do */
38
memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
38
return;
39
39
}
40
for (i = 0; i < info->num_cpus; i++) {
40
- src_pend &= ~(1 << (irq % 8));
41
- char *name = g_strdup_printf("armv7m%d", i);
41
- address_space_write(as, src_baddr + (irq / 8),
42
- sysbus_init_child_obj(obj, name, &s->armv7m[i], sizeof(s->armv7m),
42
- MEMTXATTRS_UNSPECIFIED, &src_pend, sizeof(src_pend));
43
- TYPE_ARMV7M);
43
if (irq == src->hpplpi.irq) {
44
+ /*
44
/*
45
+ * We put each CPU in its own cluster as they are logically
45
* We just made this LPI not-pending so only need to update
46
+ * distinct and may be configured differently.
47
+ */
48
+ char *name;
49
+
50
+ name = g_strdup_printf("cluster%d", i);
51
+ object_initialize_child(obj, name, &s->cluster[i],
52
+ sizeof(s->cluster[i]), TYPE_CPU_CLUSTER,
53
+ &error_abort, NULL);
54
+ qdev_prop_set_uint32(DEVICE(&s->cluster[i]), "cluster-id", i);
55
+ g_free(name);
56
+
57
+ name = g_strdup_printf("armv7m%d", i);
58
+ sysbus_init_child_obj(OBJECT(&s->cluster[i]), name,
59
+ &s->armv7m[i], sizeof(s->armv7m), TYPE_ARMV7M);
60
qdev_prop_set_string(DEVICE(&s->armv7m[i]), "cpu-type",
61
ARM_CPU_TYPE_NAME("cortex-m33"));
62
g_free(name);
63
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
64
error_propagate(errp, err);
65
return;
66
}
67
+ /*
68
+ * The cluster must be realized after the armv7m container, as
69
+ * the container's CPU object is only created on realize, and the
70
+ * CPU must exist and have been parented into the cluster before
71
+ * the cluster is realized.
72
+ */
73
+ object_property_set_bool(OBJECT(&s->cluster[i]),
74
+ true, "realized", &err);
75
+ if (err) {
76
+ error_propagate(errp, err);
77
+ return;
78
+ }
79
80
/* Connect EXP_IRQ/EXP_CPUn_IRQ GPIOs to the NVIC's lines 32 and up */
81
s->exp_irqs[i] = g_new(qemu_irq, s->exp_numirq);
82
--
46
--
83
2.20.1
47
2.25.1
84
85
diff view generated by jsdifflib
1
Rename the files that used to be iotkit.[ch] to
1
Implement the gicv3_redist_mov_vlpi() function (previously left as a
2
armsse.[ch] to reflect the fact they new cover
2
stub). This function handles the work of a VMOVI command: it marks
3
multiple Arm subsystems for embedded.
3
the vLPI not-pending on the source and pending on the destination.
4
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190121185118.18550-8-peter.maydell@linaro.org
7
Message-id: 20220408141550.1271295-35-peter.maydell@linaro.org
9
---
8
---
10
hw/arm/Makefile.objs | 2 +-
9
hw/intc/arm_gicv3_redist.c | 20 ++++++++++++++++++--
11
include/hw/arm/{iotkit.h => armsse.h} | 4 ++--
10
1 file changed, 18 insertions(+), 2 deletions(-)
12
hw/arm/{iotkit.c => armsse.c} | 2 +-
13
hw/arm/mps2-tz.c | 2 +-
14
MAINTAINERS | 4 ++--
15
default-configs/arm-softmmu.mak | 2 +-
16
6 files changed, 8 insertions(+), 8 deletions(-)
17
rename include/hw/arm/{iotkit.h => armsse.h} (99%)
18
rename hw/arm/{iotkit.c => armsse.c} (99%)
19
11
20
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
12
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
21
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/Makefile.objs
14
--- a/hw/intc/arm_gicv3_redist.c
23
+++ b/hw/arm/Makefile.objs
15
+++ b/hw/intc/arm_gicv3_redist.c
24
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
16
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_mov_vlpi(GICv3CPUState *src, uint64_t src_vptaddr,
25
obj-$(CONFIG_MPS2) += mps2.o
17
int irq, int doorbell)
26
obj-$(CONFIG_MPS2) += mps2-tz.o
18
{
27
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
19
/*
28
-obj-$(CONFIG_IOTKIT) += iotkit.o
20
- * The redistributor handling for moving a VLPI will be added
29
+obj-$(CONFIG_ARMSSE) += armsse.o
21
- * in a subsequent commit.
30
obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
22
+ * Move the specified vLPI's pending state from the source redistributor
31
obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o
23
+ * to the destination.
32
obj-$(CONFIG_FSL_IMX6UL) += fsl-imx6ul.o mcimx6ul-evk.o
24
*/
33
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/armsse.h
25
+ if (!set_pending_table_bit(src, src_vptaddr, irq, 0)) {
34
similarity index 99%
26
+ /* Not pending on source, nothing to do */
35
rename from include/hw/arm/iotkit.h
27
+ return;
36
rename to include/hw/arm/armsse.h
28
+ }
37
index XXXXXXX..XXXXXXX 100644
29
+ if (vcpu_resident(src, src_vptaddr) && irq == src->hppvlpi.irq) {
38
--- a/include/hw/arm/iotkit.h
30
+ /*
39
+++ b/include/hw/arm/armsse.h
31
+ * Update src's cached highest-priority pending vLPI if we just made
40
@@ -XXX,XX +XXX,XX @@
32
+ * it not-pending
41
* + named GPIO outputs mscexp_ns[0..15]
33
+ */
42
*/
34
+ gicv3_redist_update_vlpi(src);
43
35
+ }
44
-#ifndef IOTKIT_H
36
+ /*
45
-#define IOTKIT_H
37
+ * Mark the vLPI pending on the destination (ringing the doorbell
46
+#ifndef ARMSSE_H
38
+ * if the vCPU isn't resident)
47
+#define ARMSSE_H
39
+ */
48
40
+ gicv3_redist_process_vlpi(dest, irq, dest_vptaddr, doorbell, irq);
49
#include "hw/sysbus.h"
41
}
50
#include "hw/arm/armv7m.h"
42
51
diff --git a/hw/arm/iotkit.c b/hw/arm/armsse.c
43
void gicv3_redist_vinvall(GICv3CPUState *cs, uint64_t vptaddr)
52
similarity index 99%
53
rename from hw/arm/iotkit.c
54
rename to hw/arm/armsse.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/arm/iotkit.c
57
+++ b/hw/arm/armsse.c
58
@@ -XXX,XX +XXX,XX @@
59
#include "trace.h"
60
#include "hw/sysbus.h"
61
#include "hw/registerfields.h"
62
-#include "hw/arm/iotkit.h"
63
+#include "hw/arm/armsse.h"
64
#include "hw/arm/arm.h"
65
66
struct ARMSSEInfo {
67
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/hw/arm/mps2-tz.c
70
+++ b/hw/arm/mps2-tz.c
71
@@ -XXX,XX +XXX,XX @@
72
#include "hw/misc/mps2-fpgaio.h"
73
#include "hw/misc/tz-mpc.h"
74
#include "hw/misc/tz-msc.h"
75
-#include "hw/arm/iotkit.h"
76
+#include "hw/arm/armsse.h"
77
#include "hw/dma/pl080.h"
78
#include "hw/ssi/pl022.h"
79
#include "hw/devices.h"
80
diff --git a/MAINTAINERS b/MAINTAINERS
81
index XXXXXXX..XXXXXXX 100644
82
--- a/MAINTAINERS
83
+++ b/MAINTAINERS
84
@@ -XXX,XX +XXX,XX @@ F: hw/arm/mps2.c
85
F: hw/arm/mps2-tz.c
86
F: hw/misc/mps2-*.c
87
F: include/hw/misc/mps2-*.h
88
-F: hw/arm/iotkit.c
89
-F: include/hw/arm/iotkit.h
90
+F: hw/arm/armsse.c
91
+F: include/hw/arm/armsse.h
92
F: hw/misc/iotkit-secctl.c
93
F: include/hw/misc/iotkit-secctl.h
94
F: hw/misc/iotkit-sysctl.c
95
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
96
index XXXXXXX..XXXXXXX 100644
97
--- a/default-configs/arm-softmmu.mak
98
+++ b/default-configs/arm-softmmu.mak
99
@@ -XXX,XX +XXX,XX @@ CONFIG_MPS2_SCC=y
100
CONFIG_TZ_MPC=y
101
CONFIG_TZ_MSC=y
102
CONFIG_TZ_PPC=y
103
-CONFIG_IOTKIT=y
104
+CONFIG_ARMSSE=y
105
CONFIG_IOTKIT_SECCTL=y
106
CONFIG_IOTKIT_SYSCTL=y
107
CONFIG_IOTKIT_SYSINFO=y
108
--
44
--
109
2.20.1
45
2.25.1
110
111
diff view generated by jsdifflib
1
For the IoTKit the SRAM bank size is always 32K (15 bits); for the
1
Implement the gicv3_redist_vinvall() function (previously left as a
2
SSE-200 this is a configurable parameter, which defaults to 32K but
2
stub). This function handles the work of a VINVALL command: it must
3
can be changed when it is built into a particular SoC. For instance
3
invalidate any cached information associated with a specific vCPU.
4
the Musca-B1 board sets it to 128K (17 bits).
5
6
Make the bank size a QOM property. We follow the SSE-200 hardware in
7
naming the parameter SRAM_ADDR_WIDTH, which specifies the number of
8
address bits of a single SRAM bank.
9
4
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20190121185118.18550-11-peter.maydell@linaro.org
7
Message-id: 20220408141550.1271295-36-peter.maydell@linaro.org
13
---
8
---
14
include/hw/arm/armsse.h | 1 +
9
hw/intc/arm_gicv3_redist.c | 8 +++++++-
15
hw/arm/armsse.c | 18 ++++++++++++++++--
10
1 file changed, 7 insertions(+), 1 deletion(-)
16
2 files changed, 17 insertions(+), 2 deletions(-)
17
11
18
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
12
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
19
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/armsse.h
14
--- a/hw/intc/arm_gicv3_redist.c
21
+++ b/include/hw/arm/armsse.h
15
+++ b/hw/intc/arm_gicv3_redist.c
22
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
16
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_mov_vlpi(GICv3CPUState *src, uint64_t src_vptaddr,
23
MemoryRegion *board_memory;
17
24
uint32_t exp_numirq;
18
void gicv3_redist_vinvall(GICv3CPUState *cs, uint64_t vptaddr)
25
uint32_t mainclk_frq;
19
{
26
+ uint32_t sram_addr_width;
20
- /* The redistributor handling will be added in a subsequent commit */
27
} ARMSSE;
21
+ if (!vcpu_resident(cs, vptaddr)) {
28
22
+ /* We don't have anything cached if the vCPU isn't resident */
29
typedef struct ARMSSEInfo ARMSSEInfo;
30
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/arm/armsse.c
33
+++ b/hw/arm/armsse.c
34
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
35
DeviceState *dev_apb_ppc1;
36
DeviceState *dev_secctl;
37
DeviceState *dev_splitter;
38
+ uint32_t addr_width_max;
39
40
if (!s->board_memory) {
41
error_setg(errp, "memory property was not set");
42
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
43
return;
44
}
45
46
+ /* max SRAM_ADDR_WIDTH: 24 - log2(SRAM_NUM_BANK) */
47
+ assert(is_power_of_2(info->sram_banks));
48
+ addr_width_max = 24 - ctz32(info->sram_banks);
49
+ if (s->sram_addr_width < 1 || s->sram_addr_width > addr_width_max) {
50
+ error_setg(errp, "SRAM_ADDR_WIDTH must be between 1 and %d",
51
+ addr_width_max);
52
+ return;
23
+ return;
53
+ }
24
+ }
54
+
25
+
55
/* Handling of which devices should be available only to secure
26
+ /* Otherwise, our only cached information is the HPPVLPI info */
56
* code is usually done differently for M profile than for A profile.
27
+ gicv3_redist_update_vlpi(cs);
57
* Instead of putting some devices only into the secure address space,
28
}
58
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
29
59
for (i = 0; i < info->sram_banks; i++) {
30
void gicv3_redist_inv_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr)
60
char *ramname = g_strdup_printf("armsse.sram%d", i);
61
SysBusDevice *sbd_mpc;
62
+ uint32_t sram_bank_size = 1 << s->sram_addr_width;
63
64
- memory_region_init_ram(&s->sram[i], NULL, ramname, 0x00008000, &err);
65
+ memory_region_init_ram(&s->sram[i], NULL, ramname,
66
+ sram_bank_size, &err);
67
g_free(ramname);
68
if (err) {
69
error_propagate(errp, err);
70
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
71
}
72
/* Map the upstream end of the MPC into the right place... */
73
sbd_mpc = SYS_BUS_DEVICE(&s->mpc[i]);
74
- memory_region_add_subregion(&s->container, 0x20000000 + i * 0x8000,
75
+ memory_region_add_subregion(&s->container,
76
+ 0x20000000 + i * sram_bank_size,
77
sysbus_mmio_get_region(sbd_mpc, 1));
78
/* ...and its register interface */
79
memory_region_add_subregion(&s->container, 0x50083000 + i * 0x1000,
80
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
81
MemoryRegion *),
82
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
83
DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
84
+ DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
85
DEFINE_PROP_END_OF_LIST()
86
};
87
88
--
31
--
89
2.20.1
32
2.25.1
90
91
diff view generated by jsdifflib
1
The SSE-200 has 4 banks of SRAM, each with its own internal
1
Implement the function gicv3_redist_inv_vlpi(), which was previously
2
Memory Protection Controller. The interrupt status for these
2
left as a stub. This is the function that does the work of the INV
3
extra MPCs appears in the same security controller SECMPCINTSTATUS
3
command for a virtual interrupt.
4
register as the MPC for the IoTKit's single SRAM bank. Enhance the
5
iotkit-secctl device to allow 4 MPCs. (If the particular IoTKit/SSE
6
variant in use does not have all 4 MPCs then the unused inputs will
7
simply result in the SECMPCINTSTATUS bits being zero as required.)
8
9
The hardcoded constant "1"s in armsse.c indicate the actual number
10
of SRAM MPCs the IoTKit has, and will be replaced in the following
11
commit.
12
4
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20190121185118.18550-9-peter.maydell@linaro.org
7
Message-id: 20220408141550.1271295-37-peter.maydell@linaro.org
16
---
8
---
17
include/hw/misc/iotkit-secctl.h | 6 +++---
9
hw/intc/arm_gicv3_redist.c | 7 +++++--
18
hw/arm/armsse.c | 6 +++---
10
1 file changed, 5 insertions(+), 2 deletions(-)
19
hw/misc/iotkit-secctl.c | 5 +++--
20
3 files changed, 9 insertions(+), 8 deletions(-)
21
11
22
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
12
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
23
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/misc/iotkit-secctl.h
14
--- a/hw/intc/arm_gicv3_redist.c
25
+++ b/include/hw/misc/iotkit-secctl.h
15
+++ b/hw/intc/arm_gicv3_redist.c
26
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_vinvall(GICv3CPUState *cs, uint64_t vptaddr)
27
* + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
17
void gicv3_redist_inv_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr)
28
* + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
29
* + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
30
- * Controlling the MPC in the IoTKit:
31
- * + named GPIO input mpc_status
32
+ * Controlling the (up to) 4 MPCs in the IoTKit/SSE:
33
+ * + named GPIO inputs mpc_status[0..3]
34
* Controlling each of the 16 expansion MPCs which a system using the IoTKit
35
* might provide:
36
* + named GPIO inputs mpcexp_status[0..15]
37
@@ -XXX,XX +XXX,XX @@
38
#define IOTS_NUM_APB_EXP_PPC 4
39
#define IOTS_NUM_AHB_EXP_PPC 4
40
#define IOTS_NUM_EXP_MPC 16
41
-#define IOTS_NUM_MPC 1
42
+#define IOTS_NUM_MPC 4
43
#define IOTS_NUM_EXP_MSC 16
44
45
typedef struct IoTKitSecCtl IoTKitSecCtl;
46
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/arm/armsse.c
49
+++ b/hw/arm/armsse.c
50
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
51
sizeof(s->mpc_irq_orgate), TYPE_OR_IRQ,
52
&error_abort, NULL);
53
54
- for (i = 0; i < ARRAY_SIZE(s->mpc_irq_splitter); i++) {
55
+ for (i = 0; i < IOTS_NUM_EXP_MPC + 1; i++) {
56
char *name = g_strdup_printf("mpc-irq-splitter-%d", i);
57
SplitIRQ *splitter = &s->mpc_irq_splitter[i];
58
59
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
60
61
/* We must OR together lines from the MPC splitters to go to the NVIC */
62
object_property_set_int(OBJECT(&s->mpc_irq_orgate),
63
- IOTS_NUM_EXP_MPC + IOTS_NUM_MPC, "num-lines", &err);
64
+ IOTS_NUM_EXP_MPC + 1, "num-lines", &err);
65
if (err) {
66
error_propagate(errp, err);
67
return;
68
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
69
}
70
71
/* Wire up the splitters for the MPC IRQs */
72
- for (i = 0; i < IOTS_NUM_EXP_MPC + IOTS_NUM_MPC; i++) {
73
+ for (i = 0; i < IOTS_NUM_EXP_MPC + 1; i++) {
74
SplitIRQ *splitter = &s->mpc_irq_splitter[i];
75
DeviceState *dev_splitter = DEVICE(splitter);
76
77
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/misc/iotkit-secctl.c
80
+++ b/hw/misc/iotkit-secctl.c
81
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_mpc_status(void *opaque, int n, int level)
82
{
18
{
83
IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
19
/*
84
20
- * The redistributor handling for invalidating cached information
85
- s->mpcintstatus = deposit32(s->mpcintstatus, 0, 1, !!level);
21
- * about a VLPI will be added in a subsequent commit.
86
+ s->mpcintstatus = deposit32(s->mpcintstatus, n, 1, !!level);
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);
87
}
28
}
88
29
89
static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level)
30
void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level)
90
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
91
qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
92
qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
93
94
- qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status", 1);
95
+ qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status",
96
+ IOTS_NUM_MPC);
97
qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status,
98
"mpcexp_status", IOTS_NUM_EXP_MPC);
99
100
--
31
--
101
2.20.1
32
2.25.1
102
103
diff view generated by jsdifflib
1
Currently the ARMv7M NVIC object's realize method assumes that the
1
Update the various GIC ID and feature registers for GICv4:
2
CPU the NVIC is attached to is CPU 0, because it thinks there can
2
* PIDR2 [7:4] is the GIC architecture revision
3
only ever be one CPU in the system. To allow a dual-Cortex-M33
3
* GICD_TYPER.DVIS is 1 to indicate direct vLPI injection support
4
setup we need to remove this assumption; instead the armv7m
4
* GICR_TYPER.VLPIS is 1 to indicate redistributor support for vLPIs
5
wrapper object tells the NVIC its CPU, in the same way that it
5
* GITS_TYPER.VIRTUAL is 1 to indicate vLPI support
6
already tells the CPU what the NVIC is.
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
7
9
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20190121185118.18550-2-peter.maydell@linaro.org
12
Message-id: 20220408141550.1271295-38-peter.maydell@linaro.org
12
---
13
---
13
hw/arm/armv7m.c | 6 ++++--
14
hw/intc/gicv3_internal.h | 15 +++++++++++----
14
hw/intc/armv7m_nvic.c | 3 +--
15
hw/intc/arm_gicv3_common.c | 7 +++++--
15
2 files changed, 5 insertions(+), 4 deletions(-)
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(-)
16
21
17
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
22
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
18
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/armv7m.c
24
--- a/hw/intc/gicv3_internal.h
20
+++ b/hw/arm/armv7m.c
25
+++ b/hw/intc/gicv3_internal.h
21
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
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
+ }
22
}
90
}
23
}
91
}
24
92
25
- /* Tell the CPU where the NVIC is; it will fail realize if it doesn't
93
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
26
- * have one.
27
+ /*
28
+ * Tell the CPU where the NVIC is; it will fail realize if it doesn't
29
+ * have one. Similarly, tell the NVIC where its CPU is.
30
*/
31
s->cpu->env.nvic = &s->nvic;
32
+ s->nvic.cpu = s->cpu;
33
34
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
35
if (err != NULL) {
36
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
37
index XXXXXXX..XXXXXXX 100644
94
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/intc/armv7m_nvic.c
95
--- a/hw/intc/arm_gicv3_cpuif.c
39
+++ b/hw/intc/armv7m_nvic.c
96
+++ b/hw/intc/arm_gicv3_cpuif.c
40
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
97
@@ -XXX,XX +XXX,XX @@ static uint64_t ich_vtr_read(CPUARMState *env, const ARMCPRegInfo *ri)
41
Error *err = NULL;
98
uint64_t value;
42
int regionlen;
99
43
100
value = ((cs->num_list_regs - 1) << ICH_VTR_EL2_LISTREGS_SHIFT)
44
- s->cpu = ARM_CPU(qemu_get_cpu(0));
101
- | ICH_VTR_EL2_TDS | ICH_VTR_EL2_NV4 | ICH_VTR_EL2_A3V
45
-
102
+ | ICH_VTR_EL2_TDS | ICH_VTR_EL2_A3V
46
+ /* The armv7m container object will have set our CPU pointer */
103
| (1 << ICH_VTR_EL2_IDBITS_SHIFT)
47
if (!s->cpu || !arm_feature(&s->cpu->env, ARM_FEATURE_M)) {
104
| ((cs->vprebits - 1) << ICH_VTR_EL2_PREBITS_SHIFT)
48
error_setg(errp, "The NVIC can only be used with a Cortex-M CPU");
105
| ((cs->vpribits - 1) << ICH_VTR_EL2_PRIBITS_SHIFT);
49
return;
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
50
--
185
--
51
2.20.1
186
2.25.1
52
53
diff view generated by jsdifflib
1
The SSE-200 has two Message Handling Units (MHUs), which sit behind
1
Now that we have implemented all the GICv4 requirements, relax the
2
the APB PPC0. Wire up some unimplemented-device stubs for these,
2
error-checking on the GIC object's 'revision' property to allow a TCG
3
since we don't yet implement a real model of this device.
3
GIC to be a GICv4, whilst still constraining the KVM GIC to GICv3.
4
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.
4
13
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20190121185118.18550-16-peter.maydell@linaro.org
16
Message-id: 20220408141550.1271295-39-peter.maydell@linaro.org
8
---
17
---
9
include/hw/arm/armsse.h | 3 +++
18
hw/intc/arm_gicv3_common.c | 12 +++++++-----
10
hw/arm/armsse.c | 41 +++++++++++++++++++++++++++++++++++++++++
19
hw/intc/arm_gicv3_kvm.c | 5 +++++
11
2 files changed, 44 insertions(+)
20
2 files changed, 12 insertions(+), 5 deletions(-)
12
21
13
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
22
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
14
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/arm/armsse.h
24
--- a/hw/intc/arm_gicv3_common.c
16
+++ b/include/hw/arm/armsse.h
25
+++ b/hw/intc/arm_gicv3_common.c
17
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
18
#include "hw/watchdog/cmsdk-apb-watchdog.h"
27
GICv3State *s = ARM_GICV3_COMMON(dev);
19
#include "hw/misc/iotkit-sysctl.h"
28
int i, rdist_capacity, cpuidx;
20
#include "hw/misc/iotkit-sysinfo.h"
29
21
+#include "hw/misc/unimp.h"
30
- /* revision property is actually reserved and currently used only in order
22
#include "hw/or-irq.h"
31
- * to keep the interface compatible with GICv2 code, avoiding extra
23
#include "hw/core/split-irq.h"
32
- * conditions. However, in future it could be used, for example, if we
24
#include "hw/cpu/cluster.h"
33
- * implement GICv4.
25
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
34
+ /*
26
IoTKitSysCtl sysctl;
35
+ * This GIC device supports only revisions 3 and 4. The GICv1/v2
27
IoTKitSysCtl sysinfo;
36
+ * is a separate device.
28
37
+ * Note that subclasses of this device may impose further restrictions
29
+ UnimplementedDeviceState mhu[2];
38
+ * on the GIC revision: notably, the in-kernel KVM GIC doesn't
30
+
39
+ * support GICv4.
31
/*
40
*/
32
* 'container' holds all devices seen by all CPUs.
41
- if (s->revision != 3) {
33
* 'cpu_container[i]' is the view that CPU i has: this has the
42
+ if (s->revision != 3 && s->revision != 4) {
34
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
43
error_setg(errp, "unsupported GIC revision %d", s->revision);
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/arm/armsse.c
37
+++ b/hw/arm/armsse.c
38
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
39
int num_cpus;
40
uint32_t sys_version;
41
SysConfigFormat sys_config_format;
42
+ bool has_mhus;
43
};
44
45
static const ARMSSEInfo armsse_variants[] = {
46
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
47
.num_cpus = 1,
48
.sys_version = 0x41743,
49
.sys_config_format = IoTKitFormat,
50
+ .has_mhus = false,
51
},
52
};
53
54
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
55
sizeof(s->sysctl), TYPE_IOTKIT_SYSCTL);
56
sysbus_init_child_obj(obj, "armsse-sysinfo", &s->sysinfo,
57
sizeof(s->sysinfo), TYPE_IOTKIT_SYSINFO);
58
+ if (info->has_mhus) {
59
+ sysbus_init_child_obj(obj, "mhu0", &s->mhu[0], sizeof(s->mhu[0]),
60
+ TYPE_UNIMPLEMENTED_DEVICE);
61
+ sysbus_init_child_obj(obj, "mhu1", &s->mhu[1], sizeof(s->mhu[1]),
62
+ TYPE_UNIMPLEMENTED_DEVICE);
63
+ }
64
object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
65
sizeof(s->nmi_orgate), TYPE_OR_IRQ,
66
&error_abort, NULL);
67
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
68
* 0x40000000: timer0
69
* 0x40001000: timer1
70
* 0x40002000: dual timer
71
+ * 0x40003000: MHU0 (SSE-200 only)
72
+ * 0x40004000: MHU1 (SSE-200 only)
73
* We must configure and realize each downstream device and connect
74
* it to the appropriate PPC port; then we can realize the PPC and
75
* map its upstream ends to the right place in the container.
76
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
77
return;
44
return;
78
}
45
}
79
46
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
80
+ if (info->has_mhus) {
47
index XXXXXXX..XXXXXXX 100644
81
+ for (i = 0; i < ARRAY_SIZE(s->mhu); i++) {
48
--- a/hw/intc/arm_gicv3_kvm.c
82
+ char *name = g_strdup_printf("MHU%d", i);
49
+++ b/hw/intc/arm_gicv3_kvm.c
83
+ char *port = g_strdup_printf("port[%d]", i + 3);
50
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
84
+
51
return;
85
+ qdev_prop_set_string(DEVICE(&s->mhu[i]), "name", name);
52
}
86
+ qdev_prop_set_uint64(DEVICE(&s->mhu[i]), "size", 0x1000);
53
87
+ object_property_set_bool(OBJECT(&s->mhu[i]), true,
54
+ if (s->revision != 3) {
88
+ "realized", &err);
55
+ error_setg(errp, "unsupported GIC revision %d for in-kernel GIC",
89
+ if (err) {
56
+ s->revision);
90
+ error_propagate(errp, err);
91
+ return;
92
+ }
93
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mhu[i]), 0);
94
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr),
95
+ port, &err);
96
+ if (err) {
97
+ error_propagate(errp, err);
98
+ return;
99
+ }
100
+ g_free(name);
101
+ g_free(port);
102
+ }
103
+ }
57
+ }
104
+
58
+
105
object_property_set_bool(OBJECT(&s->apb_ppc0), true, "realized", &err);
59
if (s->security_extn) {
106
if (err) {
60
error_setg(errp, "the in-kernel VGICv3 does not implement the "
107
error_propagate(errp, err);
61
"security extensions");
108
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
109
memory_region_add_subregion(&s->container, 0x40001000, mr);
110
mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
111
memory_region_add_subregion(&s->container, 0x40002000, mr);
112
+ if (info->has_mhus) {
113
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 3);
114
+ memory_region_add_subregion(&s->container, 0x40003000, mr);
115
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 4);
116
+ memory_region_add_subregion(&s->container, 0x40004000, mr);
117
+ }
118
for (i = 0; i < IOTS_APB_PPC0_NUM_PORTS; i++) {
119
qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_nonsec", i,
120
qdev_get_gpio_in_named(dev_apb_ppc0,
121
--
62
--
122
2.20.1
63
2.25.1
123
124
diff view generated by jsdifflib
1
The SYS_VERSION and SYS_CONFIG register values differ between the
1
Everywhere we need to check which GIC version we're using, we look at
2
IoTKit and SSE-200. Make them configurable via QOM properties rather
2
vms->gic_version and use the VIRT_GIC_VERSION_* enum values, except
3
than hard-coded, and set them appropriately in the ARMSSE code that
3
in create_gic(), which copies vms->gic_version into a local 'int'
4
instantiates the IOTKIT_SYSINFO device.
4
variable and makes direct comparisons against values 2 and 3.
5
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.
5
10
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190121185118.18550-15-peter.maydell@linaro.org
13
Message-id: 20220408141550.1271295-40-peter.maydell@linaro.org
9
---
14
---
10
include/hw/misc/iotkit-sysinfo.h | 6 ++++
15
hw/arm/virt.c | 31 +++++++++++++++++++++++--------
11
hw/arm/armsse.c | 51 ++++++++++++++++++++++++++++++++
16
1 file changed, 23 insertions(+), 8 deletions(-)
12
hw/misc/iotkit-sysinfo.c | 15 ++++++++--
13
3 files changed, 70 insertions(+), 2 deletions(-)
14
17
15
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
18
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/misc/iotkit-sysinfo.h
20
--- a/hw/arm/virt.c
18
+++ b/include/hw/misc/iotkit-sysinfo.h
21
+++ b/hw/arm/virt.c
19
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
20
* Arm IoTKit and documented in
23
/* We create a standalone GIC */
21
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
24
SysBusDevice *gicbusdev;
22
* QEMU interface:
25
const char *gictype;
23
+ * + QOM property "SYS_VERSION": value to use for SYS_VERSION register
26
- int type = vms->gic_version, i;
24
+ * + QOM property "SYS_CONFIG": value to use for SYS_CONFIG register
27
+ int i;
25
* + sysbus MMIO region 0: the system information register bank
28
unsigned int smp_cpus = ms->smp.cpus;
26
*/
29
uint32_t nb_redist_regions = 0;
27
30
+ int revision;
28
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKitSysInfo {
31
29
32
- gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
30
/*< public >*/
33
+ if (vms->gic_version == VIRT_GIC_VERSION_2) {
31
MemoryRegion iomem;
34
+ gictype = gic_class_name();
32
+
35
+ } else {
33
+ /* Properties */
36
+ gictype = gicv3_class_name();
34
+ uint32_t sys_version;
37
+ }
35
+ uint32_t sys_config;
38
36
} IoTKitSysInfo;
39
+ switch (vms->gic_version) {
37
40
+ case VIRT_GIC_VERSION_2:
38
#endif
41
+ revision = 2;
39
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/armsse.c
42
+++ b/hw/arm/armsse.c
43
@@ -XXX,XX +XXX,XX @@
44
#include "hw/arm/armsse.h"
45
#include "hw/arm/arm.h"
46
47
+/* Format of the System Information block SYS_CONFIG register */
48
+typedef enum SysConfigFormat {
49
+ IoTKitFormat,
50
+ SSE200Format,
51
+} SysConfigFormat;
52
+
53
struct ARMSSEInfo {
54
const char *name;
55
int sram_banks;
56
int num_cpus;
57
+ uint32_t sys_version;
58
+ SysConfigFormat sys_config_format;
59
};
60
61
static const ARMSSEInfo armsse_variants[] = {
62
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
63
.name = TYPE_IOTKIT,
64
.sram_banks = 1,
65
.num_cpus = 1,
66
+ .sys_version = 0x41743,
67
+ .sys_config_format = IoTKitFormat,
68
},
69
};
70
71
+static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
72
+{
73
+ /* Return the SYS_CONFIG value for this SSE */
74
+ uint32_t sys_config;
75
+
76
+ switch (info->sys_config_format) {
77
+ case IoTKitFormat:
78
+ sys_config = 0;
79
+ sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
80
+ sys_config = deposit32(sys_config, 4, 4, s->sram_addr_width - 12);
81
+ break;
42
+ break;
82
+ case SSE200Format:
43
+ case VIRT_GIC_VERSION_3:
83
+ sys_config = 0;
44
+ revision = 3;
84
+ sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
85
+ sys_config = deposit32(sys_config, 4, 5, s->sram_addr_width);
86
+ sys_config = deposit32(sys_config, 24, 4, 2);
87
+ if (info->num_cpus > 1) {
88
+ sys_config = deposit32(sys_config, 10, 1, 1);
89
+ sys_config = deposit32(sys_config, 20, 4, info->sram_banks - 1);
90
+ sys_config = deposit32(sys_config, 28, 4, 2);
91
+ }
92
+ break;
45
+ break;
93
+ default:
46
+ default:
94
+ g_assert_not_reached();
47
+ g_assert_not_reached();
95
+ }
48
+ }
96
+ return sys_config;
49
vms->gic = qdev_new(gictype);
97
+}
50
- qdev_prop_set_uint32(vms->gic, "revision", type);
98
+
51
+ qdev_prop_set_uint32(vms->gic, "revision", revision);
99
/* Clock frequency in HZ of the 32KHz "slow clock" */
52
qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus);
100
#define S32KCLK (32 * 1000)
53
/* Note that the num-irq property counts both internal and external
101
54
* interrupts; there are always 32 of the former (mandated by GIC spec).
102
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
55
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
103
qdev_get_gpio_in_named(dev_apb_ppc1,
56
qdev_prop_set_bit(vms->gic, "has-security-extensions", vms->secure);
104
"cfg_sec_resp", 0));
57
}
105
58
106
+ object_property_set_int(OBJECT(&s->sysinfo), info->sys_version,
59
- if (type == 3) {
107
+ "SYS_VERSION", &err);
60
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
108
+ if (err) {
61
uint32_t redist0_capacity =
109
+ error_propagate(errp, err);
62
vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
110
+ return;
63
uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
111
+ }
64
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
112
+ object_property_set_int(OBJECT(&s->sysinfo),
65
gicbusdev = SYS_BUS_DEVICE(vms->gic);
113
+ armsse_sys_config_value(s, info),
66
sysbus_realize_and_unref(gicbusdev, &error_fatal);
114
+ "SYS_CONFIG", &err);
67
sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
115
+ if (err) {
68
- if (type == 3) {
116
+ error_propagate(errp, err);
69
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
117
+ return;
70
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
118
+ }
71
if (nb_redist_regions == 2) {
119
object_property_set_bool(OBJECT(&s->sysinfo), true, "realized", &err);
72
sysbus_mmio_map(gicbusdev, 2,
120
if (err) {
73
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
121
error_propagate(errp, err);
74
ppibase + timer_irq[irq]));
122
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
75
}
123
index XXXXXXX..XXXXXXX 100644
76
124
--- a/hw/misc/iotkit-sysinfo.c
77
- if (type == 3) {
125
+++ b/hw/misc/iotkit-sysinfo.c
78
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
126
@@ -XXX,XX +XXX,XX @@ static const int sysinfo_id[] = {
79
qemu_irq irq = qdev_get_gpio_in(vms->gic,
127
static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
80
ppibase + ARCH_GIC_MAINT_IRQ);
128
unsigned size)
81
qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
129
{
82
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
130
+ IoTKitSysInfo *s = IOTKIT_SYSINFO(opaque);
83
131
uint64_t r;
84
fdt_add_gic_node(vms);
132
85
133
switch (offset) {
86
- if (type == 3 && vms->its) {
134
case A_SYS_VERSION:
87
+ if (vms->gic_version == VIRT_GIC_VERSION_3 && vms->its) {
135
- r = 0x41743;
88
create_its(vms);
136
+ r = s->sys_version;
89
- } else if (type == 2) {
137
break;
90
+ } else if (vms->gic_version == VIRT_GIC_VERSION_2) {
138
91
create_v2m(vms);
139
case A_SYS_CONFIG:
92
}
140
- r = 0x31;
141
+ r = s->sys_config;
142
break;
143
case A_PID4 ... A_CID3:
144
r = sysinfo_id[(offset - A_PID4) / 4];
145
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps iotkit_sysinfo_ops = {
146
.valid.max_access_size = 4,
147
};
148
149
+static Property iotkit_sysinfo_props[] = {
150
+ DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysInfo, sys_version, 0),
151
+ DEFINE_PROP_UINT32("SYS_CONFIG", IoTKitSysInfo, sys_config, 0),
152
+ DEFINE_PROP_END_OF_LIST()
153
+};
154
+
155
static void iotkit_sysinfo_init(Object *obj)
156
{
157
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
158
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysinfo_init(Object *obj)
159
160
static void iotkit_sysinfo_class_init(ObjectClass *klass, void *data)
161
{
162
+ DeviceClass *dc = DEVICE_CLASS(klass);
163
+
164
/*
165
* This device has no guest-modifiable state and so it
166
* does not need a reset function or VMState.
167
*/
168
+
169
+ dc->props = iotkit_sysinfo_props;
170
}
93
}
171
172
static const TypeInfo iotkit_sysinfo_info = {
173
--
94
--
174
2.20.1
95
2.25.1
175
176
diff view generated by jsdifflib
1
Give each CPU its own container memory region. This is necessary
1
In several places in virt.c we calculate the number of redistributors that
2
for two reasons:
2
fit in a region of our memory map, which is the size of the region
3
* some devices are instantiated one per CPU and the CPU sees only
3
divided by the size of a single redistributor frame. For GICv4, the
4
its own device
4
redistributor frame is a different size from that for GICv3. Abstract
5
* since a memory region can only be put into one container, we must
5
out the calculation of redistributor region capacity so that we have
6
give each armv7m object a different MemoryRegion as its 'memory'
6
one place we need to change to handle GICv4 rather than several.
7
property, or a dual-CPU configuration will assert on realize when
8
the second armv7m object tries to put the MR into a container when
9
it is already in the first armv7m object's container
10
7
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20190121185118.18550-13-peter.maydell@linaro.org
10
Message-id: 20220408141550.1271295-41-peter.maydell@linaro.org
14
---
11
---
15
include/hw/arm/armsse.h | 10 ++++++++++
12
include/hw/arm/virt.h | 9 +++++++--
16
hw/arm/armsse.c | 22 ++++++++++++++++++++--
13
hw/arm/virt.c | 11 ++++-------
17
2 files changed, 30 insertions(+), 2 deletions(-)
14
2 files changed, 11 insertions(+), 9 deletions(-)
18
15
19
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
16
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/arm/armsse.h
18
--- a/include/hw/arm/virt.h
22
+++ b/include/hw/arm/armsse.h
19
+++ b/include/hw/arm/virt.h
23
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
20
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(VirtMachineState, VirtMachineClass, VIRT_MACHINE)
24
IoTKitSysCtl sysctl;
21
void virt_acpi_setup(VirtMachineState *vms);
25
IoTKitSysCtl sysinfo;
22
bool virt_is_acpi_enabled(VirtMachineState *vms);
26
23
27
+ /*
24
+/* Return number of redistributors that fit in the specified region */
28
+ * 'container' holds all devices seen by all CPUs.
25
+static uint32_t virt_redist_capacity(VirtMachineState *vms, int region)
29
+ * 'cpu_container[i]' is the view that CPU i has: this has the
26
+{
30
+ * per-CPU devices of that CPU, plus as the background 'container'
27
+ return vms->memmap[region].size / GICV3_REDIST_SIZE;
31
+ * (or an alias of it, since we can only use it directly once).
28
+}
32
+ * container_alias[i] is the alias of 'container' used by CPU i+1;
29
+
33
+ * CPU 0 can use 'container' directly.
30
/* Return the number of used redistributor regions */
34
+ */
31
static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
35
MemoryRegion container;
32
{
36
+ MemoryRegion container_alias[SSE_MAX_CPUS - 1];
33
- uint32_t redist0_capacity =
37
+ MemoryRegion cpu_container[SSE_MAX_CPUS];
34
- vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
38
MemoryRegion alias1;
35
+ uint32_t redist0_capacity = virt_redist_capacity(vms, VIRT_GIC_REDIST);
39
MemoryRegion alias2;
36
40
MemoryRegion alias3;
37
assert(vms->gic_version == VIRT_GIC_VERSION_3);
41
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
38
39
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
42
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/arm/armsse.c
41
--- a/hw/arm/virt.c
44
+++ b/hw/arm/armsse.c
42
+++ b/hw/arm/virt.c
45
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
43
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
46
qdev_prop_set_string(DEVICE(&s->armv7m[i]), "cpu-type",
47
ARM_CPU_TYPE_NAME("cortex-m33"));
48
g_free(name);
49
+ name = g_strdup_printf("arm-sse-cpu-container%d", i);
50
+ memory_region_init(&s->cpu_container[i], obj, name, UINT64_MAX);
51
+ g_free(name);
52
+ if (i > 0) {
53
+ name = g_strdup_printf("arm-sse-container-alias%d", i);
54
+ memory_region_init_alias(&s->container_alias[i - 1], obj,
55
+ name, &s->container, 0, UINT64_MAX);
56
+ g_free(name);
57
+ }
58
}
44
}
59
45
60
sysbus_init_child_obj(obj, "secctl", &s->secctl, sizeof(s->secctl),
46
if (vms->gic_version == VIRT_GIC_VERSION_3) {
61
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
47
- uint32_t redist0_capacity =
62
* 0x50000000..0x5fffffff alias of 0x40000000..0x4fffffff
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.
63
*/
64
*/
64
65
if (vms->gic_version == VIRT_GIC_VERSION_3) {
65
- memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
66
- virt_max_cpus =
66
+ memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -2);
67
- vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
67
68
- virt_max_cpus +=
68
for (i = 0; i < info->num_cpus; i++) {
69
- vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
69
DeviceState *cpudev = DEVICE(&s->armv7m[i]);
70
+ virt_max_cpus = virt_redist_capacity(vms, VIRT_GIC_REDIST) +
70
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
71
+ virt_redist_capacity(vms, VIRT_HIGH_GIC_REDIST2);
71
return;
72
} else {
72
}
73
virt_max_cpus = GIC_NCPU;
73
}
74
}
74
- object_property_set_link(cpuobj, OBJECT(&s->container), "memory", &err);
75
+
76
+ if (i > 0) {
77
+ memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
78
+ &s->container_alias[i - 1], -1);
79
+ } else {
80
+ memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
81
+ &s->container, -1);
82
+ }
83
+ object_property_set_link(cpuobj, OBJECT(&s->cpu_container[i]),
84
+ "memory", &err);
85
if (err) {
86
error_propagate(errp, err);
87
return;
88
--
75
--
89
2.20.1
76
2.25.1
90
91
diff view generated by jsdifflib
1
The SSE-200 has a CPU_IDENTITY register block, which is a set of
1
Add support for the TCG GICv4 to the virt board. For the board,
2
read-only registers. As well as the usual PID/CID registers, there
2
the GICv4 is very similar to the GICv3, with the only difference
3
is a single CPUID register which indicates whether the CPU is CPU 0
3
being the size of the redistributor frame. The changes here are thus:
4
or CPU 1. Implement a model of this register block.
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
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.
5
11
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190121185118.18550-20-peter.maydell@linaro.org
14
Message-id: 20220408141550.1271295-42-peter.maydell@linaro.org
9
---
15
---
10
hw/misc/Makefile.objs | 1 +
16
docs/system/arm/virt.rst | 5 ++-
11
include/hw/misc/armsse-cpuid.h | 41 ++++++++++
17
include/hw/arm/virt.h | 12 +++++--
12
hw/misc/armsse-cpuid.c | 134 ++++++++++++++++++++++++++++++++
18
hw/arm/virt.c | 70 ++++++++++++++++++++++++++++++----------
13
MAINTAINERS | 2 +
19
3 files changed, 67 insertions(+), 20 deletions(-)
14
default-configs/arm-softmmu.mak | 1 +
15
hw/misc/trace-events | 4 +
16
6 files changed, 183 insertions(+)
17
create mode 100644 include/hw/misc/armsse-cpuid.h
18
create mode 100644 hw/misc/armsse-cpuid.c
19
20
20
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
21
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
21
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/Makefile.objs
23
--- a/docs/system/arm/virt.rst
23
+++ b/hw/misc/Makefile.objs
24
+++ b/docs/system/arm/virt.rst
24
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_TZ_PPC) += tz-ppc.o
25
@@ -XXX,XX +XXX,XX @@ gic-version
25
obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
26
GICv2. Note that this limits the number of CPUs to 8.
26
obj-$(CONFIG_IOTKIT_SYSCTL) += iotkit-sysctl.o
27
``3``
27
obj-$(CONFIG_IOTKIT_SYSINFO) += iotkit-sysinfo.o
28
GICv3. This allows up to 512 CPUs.
28
+obj-$(CONFIG_ARMSSE_CPUID) += armsse-cpuid.o
29
+ ``4``
29
30
+ GICv4. Requires ``virtualization`` to be ``on``; allows up to 317 CPUs.
30
obj-$(CONFIG_PVPANIC) += pvpanic.o
31
``host``
31
obj-$(CONFIG_AUX) += auxbus.o
32
Use the same GIC version the host provides, when using KVM
32
diff --git a/include/hw/misc/armsse-cpuid.h b/include/hw/misc/armsse-cpuid.h
33
``max``
33
new file mode 100644
34
Use the best GIC version possible (same as host when using KVM;
34
index XXXXXXX..XXXXXXX
35
- currently same as ``3``` for TCG, but this may change in future)
35
--- /dev/null
36
+ with TCG this is currently ``3`` if ``virtualization`` is ``off`` and
36
+++ b/include/hw/misc/armsse-cpuid.h
37
+ ``4`` if ``virtualization`` is ``on``, but this may change in future)
37
@@ -XXX,XX +XXX,XX @@
38
38
+/*
39
its
39
+ * ARM SSE-200 CPU_IDENTITY register block
40
Set ``on``/``off`` to enable/disable ITS instantiation. The default is ``on``
40
+ *
41
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
41
+ * Copyright (c) 2019 Linaro Limited
42
index XXXXXXX..XXXXXXX 100644
42
+ * Written by Peter Maydell
43
--- a/include/hw/arm/virt.h
43
+ *
44
+++ b/include/hw/arm/virt.h
44
+ * This program is free software; you can redistribute it and/or modify
45
@@ -XXX,XX +XXX,XX @@ typedef enum VirtGICType {
45
+ * it under the terms of the GNU General Public License version 2 or
46
VIRT_GIC_VERSION_HOST,
46
+ * (at your option) any later version.
47
VIRT_GIC_VERSION_2,
47
+ */
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;
48
+
59
+
49
+/*
60
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
50
+ * This is a model of the "CPU_IDENTITY" register block which is part of the
61
+ redist_size = GICV3_REDIST_SIZE;
51
+ * Arm SSE-200 and documented in
62
+ } else {
52
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
63
+ redist_size = GICV4_REDIST_SIZE;
53
+ *
64
+ }
54
+ * QEMU interface:
65
+ return vms->memmap[region].size / redist_size;
55
+ * + QOM property "CPUID": the value to use for the CPUID register
66
}
56
+ * + sysbus MMIO region 0: the system information register bank
67
57
+ */
68
/* Return the number of used redistributor regions */
58
+
69
@@ -XXX,XX +XXX,XX @@ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
59
+#ifndef HW_MISC_ARMSSE_CPUID_H
70
{
60
+#define HW_MISC_ARMSSE_CPUID_H
71
uint32_t redist0_capacity = virt_redist_capacity(vms, VIRT_GIC_REDIST);
61
+
72
62
+#include "hw/sysbus.h"
73
- assert(vms->gic_version == VIRT_GIC_VERSION_3);
63
+
74
+ assert(vms->gic_version != VIRT_GIC_VERSION_2);
64
+#define TYPE_ARMSSE_CPUID "armsse-cpuid"
75
65
+#define ARMSSE_CPUID(obj) OBJECT_CHECK(ARMSSECPUID, (obj), TYPE_ARMSSE_CPUID)
76
return (MACHINE(vms)->smp.cpus > redist0_capacity &&
66
+
77
vms->highmem_redists) ? 2 : 1;
67
+typedef struct ARMSSECPUID {
78
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
68
+ /*< private >*/
79
index XXXXXXX..XXXXXXX 100644
69
+ SysBusDevice parent_obj;
80
--- a/hw/arm/virt.c
70
+
81
+++ b/hw/arm/virt.c
71
+ /*< public >*/
82
@@ -XXX,XX +XXX,XX @@ static void fdt_add_gic_node(VirtMachineState *vms)
72
+ MemoryRegion iomem;
83
qemu_fdt_setprop_cell(ms->fdt, nodename, "#address-cells", 0x2);
73
+
84
qemu_fdt_setprop_cell(ms->fdt, nodename, "#size-cells", 0x2);
74
+ /* Properties */
85
qemu_fdt_setprop(ms->fdt, nodename, "ranges", NULL, 0);
75
+ uint32_t cpuid;
86
- if (vms->gic_version == VIRT_GIC_VERSION_3) {
76
+} ARMSSECPUID;
87
+ if (vms->gic_version != VIRT_GIC_VERSION_2) {
77
+
88
int nb_redist_regions = virt_gicv3_redist_region_count(vms);
78
+#endif
89
79
diff --git a/hw/misc/armsse-cpuid.c b/hw/misc/armsse-cpuid.c
90
qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
80
new file mode 100644
91
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
81
index XXXXXXX..XXXXXXX
92
case VIRT_GIC_VERSION_3:
82
--- /dev/null
93
revision = 3;
83
+++ b/hw/misc/armsse-cpuid.c
94
break;
84
@@ -XXX,XX +XXX,XX @@
95
+ case VIRT_GIC_VERSION_4:
85
+/*
96
+ revision = 4;
86
+ * ARM SSE-200 CPU_IDENTITY register block
97
+ break;
87
+ *
98
default:
88
+ * Copyright (c) 2019 Linaro Limited
99
g_assert_not_reached();
89
+ * Written by Peter Maydell
100
}
90
+ *
101
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
91
+ * This program is free software; you can redistribute it and/or modify
102
qdev_prop_set_bit(vms->gic, "has-security-extensions", vms->secure);
92
+ * it under the terms of the GNU General Public License version 2 or
103
}
93
+ * (at your option) any later version.
104
94
+ */
105
- if (vms->gic_version == VIRT_GIC_VERSION_3) {
95
+
106
+ if (vms->gic_version != VIRT_GIC_VERSION_2) {
96
+/*
107
uint32_t redist0_capacity = virt_redist_capacity(vms, VIRT_GIC_REDIST);
97
+ * This is a model of the "CPU_IDENTITY" register block which is part of the
108
uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
98
+ * Arm SSE-200 and documented in
109
99
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
110
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
100
+ *
111
gicbusdev = SYS_BUS_DEVICE(vms->gic);
101
+ * It consists of one read-only CPUID register (set by QOM property), plus the
112
sysbus_realize_and_unref(gicbusdev, &error_fatal);
102
+ * usual ID registers.
113
sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
103
+ */
114
- if (vms->gic_version == VIRT_GIC_VERSION_3) {
104
+
115
+ if (vms->gic_version != VIRT_GIC_VERSION_2) {
105
+#include "qemu/osdep.h"
116
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
106
+#include "qemu/log.h"
117
if (nb_redist_regions == 2) {
107
+#include "trace.h"
118
sysbus_mmio_map(gicbusdev, 2,
108
+#include "qapi/error.h"
119
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
109
+#include "sysemu/sysemu.h"
120
ppibase + timer_irq[irq]));
110
+#include "hw/sysbus.h"
121
}
111
+#include "hw/registerfields.h"
122
112
+#include "hw/misc/armsse-cpuid.h"
123
- if (vms->gic_version == VIRT_GIC_VERSION_3) {
113
+
124
+ if (vms->gic_version != VIRT_GIC_VERSION_2) {
114
+REG32(CPUID, 0x0)
125
qemu_irq irq = qdev_get_gpio_in(vms->gic,
115
+REG32(PID4, 0xfd0)
126
ppibase + ARCH_GIC_MAINT_IRQ);
116
+REG32(PID5, 0xfd4)
127
qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
117
+REG32(PID6, 0xfd8)
128
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
118
+REG32(PID7, 0xfdc)
129
119
+REG32(PID0, 0xfe0)
130
fdt_add_gic_node(vms);
120
+REG32(PID1, 0xfe4)
131
121
+REG32(PID2, 0xfe8)
132
- if (vms->gic_version == VIRT_GIC_VERSION_3 && vms->its) {
122
+REG32(PID3, 0xfec)
133
+ if (vms->gic_version != VIRT_GIC_VERSION_2 && vms->its) {
123
+REG32(CID0, 0xff0)
134
create_its(vms);
124
+REG32(CID1, 0xff4)
135
} else if (vms->gic_version == VIRT_GIC_VERSION_2) {
125
+REG32(CID2, 0xff8)
136
create_v2m(vms);
126
+REG32(CID3, 0xffc)
137
@@ -XXX,XX +XXX,XX @@ static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx)
127
+
138
* purposes are to make TCG consistent (with 64-bit KVM hosts)
128
+/* PID/CID values */
139
* and to improve SGI efficiency.
129
+static const int sysinfo_id[] = {
140
*/
130
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
141
- if (vms->gic_version == VIRT_GIC_VERSION_3) {
131
+ 0x58, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
142
- clustersz = GICV3_TARGETLIST_BITS;
132
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
143
- } else {
133
+};
144
+ if (vms->gic_version == VIRT_GIC_VERSION_2) {
134
+
145
clustersz = GIC_TARGETLIST_BITS;
135
+static uint64_t armsse_cpuid_read(void *opaque, hwaddr offset,
146
+ } else {
136
+ unsigned size)
147
+ clustersz = GICV3_TARGETLIST_BITS;
137
+{
148
}
138
+ ARMSSECPUID *s = ARMSSE_CPUID(opaque);
149
}
139
+ uint64_t r;
150
return arm_cpu_mp_affinity(idx, clustersz);
140
+
151
@@ -XXX,XX +XXX,XX @@ static void finalize_gic_version(VirtMachineState *vms)
141
+ switch (offset) {
152
error_report(
142
+ case A_CPUID:
153
"gic-version=3 is not supported with kernel-irqchip=off");
143
+ r = s->cpuid;
154
exit(1);
144
+ break;
155
+ case VIRT_GIC_VERSION_4:
145
+ case A_PID4 ... A_CID3:
156
+ error_report(
146
+ r = sysinfo_id[(offset - A_PID4) / 4];
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";
147
+ break;
234
+ break;
148
+ default:
235
+ default:
149
+ qemu_log_mask(LOG_GUEST_ERROR,
236
+ val = "2";
150
+ "SSE CPU_IDENTITY read: bad offset 0x%x\n", (int)offset);
151
+ r = 0;
152
+ break;
237
+ break;
153
+ }
238
+ }
154
+ trace_armsse_cpuid_read(offset, r, size);
239
return g_strdup(val);
155
+ return r;
240
}
156
+}
241
157
+
242
@@ -XXX,XX +XXX,XX @@ static void virt_set_gic_version(Object *obj, const char *value, Error **errp)
158
+static void armsse_cpuid_write(void *opaque, hwaddr offset,
243
{
159
+ uint64_t value, unsigned size)
244
VirtMachineState *vms = VIRT_MACHINE(obj);
160
+{
245
161
+ trace_armsse_cpuid_write(offset, value, size);
246
- if (!strcmp(value, "3")) {
162
+
247
+ if (!strcmp(value, "4")) {
163
+ qemu_log_mask(LOG_GUEST_ERROR,
248
+ vms->gic_version = VIRT_GIC_VERSION_4;
164
+ "SSE CPU_IDENTITY: write to RO offset 0x%x\n", (int)offset);
249
+ } else if (!strcmp(value, "3")) {
165
+}
250
vms->gic_version = VIRT_GIC_VERSION_3;
166
+
251
} else if (!strcmp(value, "2")) {
167
+static const MemoryRegionOps armsse_cpuid_ops = {
252
vms->gic_version = VIRT_GIC_VERSION_2;
168
+ .read = armsse_cpuid_read,
253
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
169
+ .write = armsse_cpuid_write,
254
virt_set_gic_version);
170
+ .endianness = DEVICE_LITTLE_ENDIAN,
255
object_class_property_set_description(oc, "gic-version",
171
+ /* byte/halfword accesses are just zero-padded on reads and writes */
256
"Set GIC version. "
172
+ .impl.min_access_size = 4,
257
- "Valid values are 2, 3, host and max");
173
+ .impl.max_access_size = 4,
258
+ "Valid values are 2, 3, 4, host and max");
174
+ .valid.min_access_size = 1,
259
175
+ .valid.max_access_size = 4,
260
object_class_property_add_str(oc, "iommu", virt_get_iommu, virt_set_iommu);
176
+};
261
object_class_property_set_description(oc, "iommu",
177
+
178
+static Property armsse_cpuid_props[] = {
179
+ DEFINE_PROP_UINT32("CPUID", ARMSSECPUID, cpuid, 0),
180
+ DEFINE_PROP_END_OF_LIST()
181
+};
182
+
183
+static void armsse_cpuid_init(Object *obj)
184
+{
185
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
186
+ ARMSSECPUID *s = ARMSSE_CPUID(obj);
187
+
188
+ memory_region_init_io(&s->iomem, obj, &armsse_cpuid_ops,
189
+ s, "armsse-cpuid", 0x1000);
190
+ sysbus_init_mmio(sbd, &s->iomem);
191
+}
192
+
193
+static void armsse_cpuid_class_init(ObjectClass *klass, void *data)
194
+{
195
+ DeviceClass *dc = DEVICE_CLASS(klass);
196
+
197
+ /*
198
+ * This device has no guest-modifiable state and so it
199
+ * does not need a reset function or VMState.
200
+ */
201
+
202
+ dc->props = armsse_cpuid_props;
203
+}
204
+
205
+static const TypeInfo armsse_cpuid_info = {
206
+ .name = TYPE_ARMSSE_CPUID,
207
+ .parent = TYPE_SYS_BUS_DEVICE,
208
+ .instance_size = sizeof(ARMSSECPUID),
209
+ .instance_init = armsse_cpuid_init,
210
+ .class_init = armsse_cpuid_class_init,
211
+};
212
+
213
+static void armsse_cpuid_register_types(void)
214
+{
215
+ type_register_static(&armsse_cpuid_info);
216
+}
217
+
218
+type_init(armsse_cpuid_register_types);
219
diff --git a/MAINTAINERS b/MAINTAINERS
220
index XXXXXXX..XXXXXXX 100644
221
--- a/MAINTAINERS
222
+++ b/MAINTAINERS
223
@@ -XXX,XX +XXX,XX @@ F: hw/misc/iotkit-sysctl.c
224
F: include/hw/misc/iotkit-sysctl.h
225
F: hw/misc/iotkit-sysinfo.c
226
F: include/hw/misc/iotkit-sysinfo.h
227
+F: hw/misc/armsse-cpuid.c
228
+F: include/hw/misc/armsse-cpuid.h
229
230
Musicpal
231
M: Jan Kiszka <jan.kiszka@web.de>
232
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
233
index XXXXXXX..XXXXXXX 100644
234
--- a/default-configs/arm-softmmu.mak
235
+++ b/default-configs/arm-softmmu.mak
236
@@ -XXX,XX +XXX,XX @@ CONFIG_ARMSSE=y
237
CONFIG_IOTKIT_SECCTL=y
238
CONFIG_IOTKIT_SYSCTL=y
239
CONFIG_IOTKIT_SYSINFO=y
240
+CONFIG_ARMSSE_CPUID=y
241
242
CONFIG_VERSATILE=y
243
CONFIG_VERSATILE_PCI=y
244
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
245
index XXXXXXX..XXXXXXX 100644
246
--- a/hw/misc/trace-events
247
+++ b/hw/misc/trace-events
248
@@ -XXX,XX +XXX,XX @@ iotkit_sysinfo_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysI
249
iotkit_sysctl_read(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysCtl read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
250
iotkit_sysctl_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysCtl write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
251
iotkit_sysctl_reset(void) "IoTKit SysCtl: reset"
252
+
253
+# hw/misc/armsse-cpuid.c
254
+armsse_cpuid_read(uint64_t offset, uint64_t data, unsigned size) "SSE-200 CPU_IDENTITY read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
255
+armsse_cpuid_write(uint64_t offset, uint64_t data, unsigned size) "SSE-200 CPU_IDENTITY write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
256
--
262
--
257
2.20.1
263
2.25.1
258
259
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Update isar fields per ARM DDI0487 H.a.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
---
9
---
7
linux-user/elfload.c | 9 +++++++++
10
target/arm/cpu.h | 24 ++++++++++++++++++++++++
8
1 file changed, 9 insertions(+)
11
1 file changed, 24 insertions(+)
9
12
10
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
11
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
12
--- a/linux-user/elfload.c
15
--- a/target/arm/cpu.h
13
+++ b/linux-user/elfload.c
16
+++ b/target/arm/cpu.h
14
@@ -XXX,XX +XXX,XX @@ enum {
17
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, CCIDX, 24, 4)
15
ARM_HWCAP_A64_ASIMDDP = 1 << 20,
18
FIELD(ID_MMFR4, EVT, 28, 4)
16
ARM_HWCAP_A64_SHA512 = 1 << 21,
19
17
ARM_HWCAP_A64_SVE = 1 << 22,
20
FIELD(ID_MMFR5, ETS, 0, 4)
18
+ ARM_HWCAP_A64_ASIMDFHM = 1 << 23,
21
+FIELD(ID_MMFR5, NTLBPA, 4, 4)
19
+ ARM_HWCAP_A64_DIT = 1 << 24,
22
20
+ ARM_HWCAP_A64_USCAT = 1 << 25,
23
FIELD(ID_PFR0, STATE0, 0, 4)
21
+ ARM_HWCAP_A64_ILRCPC = 1 << 26,
24
FIELD(ID_PFR0, STATE1, 4, 4)
22
+ ARM_HWCAP_A64_FLAGM = 1 << 27,
25
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64ISAR1, SPECRES, 40, 4)
23
+ ARM_HWCAP_A64_SSBS = 1 << 28,
26
FIELD(ID_AA64ISAR1, BF16, 44, 4)
24
+ ARM_HWCAP_A64_SB = 1 << 29,
27
FIELD(ID_AA64ISAR1, DGH, 48, 4)
25
+ ARM_HWCAP_A64_PACA = 1 << 30,
28
FIELD(ID_AA64ISAR1, I8MM, 52, 4)
26
+ ARM_HWCAP_A64_PACG = 1UL << 31,
29
+FIELD(ID_AA64ISAR1, XS, 56, 4)
27
};
30
+FIELD(ID_AA64ISAR1, LS64, 60, 4)
28
31
+
29
#define ELF_HWCAP get_elf_hwcap()
32
+FIELD(ID_AA64ISAR2, WFXT, 0, 4)
33
+FIELD(ID_AA64ISAR2, RPRES, 4, 4)
34
+FIELD(ID_AA64ISAR2, GPA3, 8, 4)
35
+FIELD(ID_AA64ISAR2, APA3, 12, 4)
36
+FIELD(ID_AA64ISAR2, MOPS, 16, 4)
37
+FIELD(ID_AA64ISAR2, BC, 20, 4)
38
+FIELD(ID_AA64ISAR2, PAC_FRAC, 24, 4)
39
40
FIELD(ID_AA64PFR0, EL0, 0, 4)
41
FIELD(ID_AA64PFR0, EL1, 4, 4)
42
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR1, SSBS, 4, 4)
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)
30
--
84
--
31
2.20.1
85
2.25.1
32
86
33
87
diff view generated by jsdifflib
1
From: kumar sourav <sourav.jb1988@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
set object owner in memory_region_init_ram() instead
3
Update SCR_EL3 fields per ARM DDI0487 H.a.
4
of NULL.
5
4
6
Signed-off-by: kumar sourav <sourav.jb1988@gmail.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Message-id: 20190125155630.17430-1-sourav.jb1988@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
8
---
12
hw/arm/nrf51_soc.c | 3 ++-
9
target/arm/cpu.h | 12 ++++++++++++
13
1 file changed, 2 insertions(+), 1 deletion(-)
10
1 file changed, 12 insertions(+)
14
11
15
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
12
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/nrf51_soc.c
14
--- a/target/arm/cpu.h
18
+++ b/hw/arm/nrf51_soc.c
15
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
16
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
20
}
17
#define SCR_FIEN (1U << 21)
21
memory_region_add_subregion(&s->container, NRF51_FLASH_BASE, &s->flash);
18
#define SCR_ENSCXT (1U << 25)
22
19
#define SCR_ATA (1U << 26)
23
- memory_region_init_ram(&s->sram, NULL, "nrf51.sram", s->sram_size, &err);
20
+#define SCR_FGTEN (1U << 27)
24
+ memory_region_init_ram(&s->sram, OBJECT(s), "nrf51.sram", s->sram_size,
21
+#define SCR_ECVEN (1U << 28)
25
+ &err);
22
+#define SCR_TWEDEN (1U << 29)
26
if (err) {
23
+#define SCR_TWEDEL MAKE_64BIT_MASK(30, 4)
27
error_propagate(errp, err);
24
+#define SCR_TME (1ULL << 34)
28
return;
25
+#define SCR_AMVOFFEN (1ULL << 35)
26
+#define SCR_ENAS0 (1ULL << 36)
27
+#define SCR_ADEN (1ULL << 37)
28
+#define SCR_HXEN (1ULL << 38)
29
+#define SCR_TRNDR (1ULL << 40)
30
+#define SCR_ENTP2 (1ULL << 41)
31
+#define SCR_GPF (1ULL << 48)
32
33
#define HSTR_TTEE (1 << 16)
34
#define HSTR_TJDBX (1 << 17)
29
--
35
--
30
2.20.1
36
2.25.1
31
37
32
38
diff view generated by jsdifflib
1
From: Remi Denis-Courmont <remi.denis.courmont@huawei.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Since QEMU does not support the ARMv8.2-LVA, Large Virtual Address,
3
Update SCTLR_ELx fields per ARM DDI0487 H.a.
4
extension (yet), the VA address space is 48-bits plus a sign bit. User
5
mode can only handle the positive half of the address space, so that
6
makes a limit of 48 bits.
7
4
8
(With LVA, it would be 53 and 52 bits respectively.)
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
The incorrectly large address space conflicts with PAuth instructions,
11
which use bits 48-54 and 56-63 for the pointer authentication code. This
12
also conflicts with (as yet unsupported by QEMU) data tagging and with
13
the ARMv8.5-MTE extension.
14
15
Signed-off-by: Remi Denis-Courmont <remi.denis.courmont@huawei.com>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
8
---
19
target/arm/cpu.h | 2 +-
9
target/arm/cpu.h | 14 ++++++++++++++
20
1 file changed, 1 insertion(+), 1 deletion(-)
10
1 file changed, 14 insertions(+)
21
11
22
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
23
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/cpu.h
14
--- a/target/arm/cpu.h
25
+++ b/target/arm/cpu.h
15
+++ b/target/arm/cpu.h
26
@@ -XXX,XX +XXX,XX @@ bool write_cpustate_to_list(ARMCPU *cpu);
16
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
27
17
#define SCTLR_ATA0 (1ULL << 42) /* v8.5-MemTag */
28
#if defined(TARGET_AARCH64)
18
#define SCTLR_ATA (1ULL << 43) /* v8.5-MemTag */
29
# define TARGET_PHYS_ADDR_SPACE_BITS 48
19
#define SCTLR_DSSBS_64 (1ULL << 44) /* v8.5, AArch64 only */
30
-# define TARGET_VIRT_ADDR_SPACE_BITS 64
20
+#define SCTLR_TWEDEn (1ULL << 45) /* FEAT_TWED */
31
+# define TARGET_VIRT_ADDR_SPACE_BITS 48
21
+#define SCTLR_TWEDEL MAKE_64_MASK(46, 4) /* FEAT_TWED */
32
#else
22
+#define SCTLR_TMT0 (1ULL << 50) /* FEAT_TME */
33
# define TARGET_PHYS_ADDR_SPACE_BITS 40
23
+#define SCTLR_TMT (1ULL << 51) /* FEAT_TME */
34
# define TARGET_VIRT_ADDR_SPACE_BITS 32
24
+#define SCTLR_TME0 (1ULL << 52) /* FEAT_TME */
25
+#define SCTLR_TME (1ULL << 53) /* FEAT_TME */
26
+#define SCTLR_EnASR (1ULL << 54) /* FEAT_LS64_V */
27
+#define SCTLR_EnAS0 (1ULL << 55) /* FEAT_LS64_ACCDATA */
28
+#define SCTLR_EnALS (1ULL << 56) /* FEAT_LS64 */
29
+#define SCTLR_EPAN (1ULL << 57) /* FEAT_PAN3 */
30
+#define SCTLR_EnTP2 (1ULL << 60) /* FEAT_SME */
31
+#define SCTLR_NMI (1ULL << 61) /* FEAT_NMI */
32
+#define SCTLR_SPINTMASK (1ULL << 62) /* FEAT_NMI */
33
+#define SCTLR_TIDCP (1ULL << 63) /* FEAT_TIDCP1 */
34
35
#define CPTR_TCPAC (1U << 31)
36
#define CPTR_TTA (1U << 20)
35
--
37
--
36
2.20.1
38
2.25.1
37
39
38
40
diff view generated by jsdifflib
1
In disas_simd_indexed(), for the case of "complex fp", each indexable
1
From: Richard Henderson <richard.henderson@linaro.org>
2
element is a complex pair, so the total size is twice that indicated
3
in the 'size' field in the encoding. We were trying to do this
4
"double the size" operation with a left shift by 1, but this is
5
incorrect because the 'size' field is a MO_8/MO_16/MO_32/MO_64
6
value, and doubling the size should be done by a simple increment.
7
2
8
This meant we were mishandling FCMLA (by element) of values where
3
Bool is a more appropriate type for this value.
9
the real and imaginary parts are 32-bit floats, and would incorrectly
4
Move the member down in the struct to keep the
10
UNDEF this encoding. (No other insns take this code path, and for
5
bool type members together and remove a hole.
11
16-bit floats it happens that 1 << 1 and 1 + 1 are both the same).
12
6
13
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
16
Message-id: 20190129140411.682-3-peter.maydell@linaro.org
17
---
10
---
11
target/arm/translate.h | 2 +-
18
target/arm/translate-a64.c | 2 +-
12
target/arm/translate-a64.c | 2 +-
19
1 file changed, 1 insertion(+), 1 deletion(-)
13
target/arm/translate.c | 2 +-
14
3 files changed, 3 insertions(+), 3 deletions(-)
20
15
16
diff --git a/target/arm/translate.h b/target/arm/translate.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.h
19
+++ b/target/arm/translate.h
20
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
21
* so that top level loop can generate correct syndrome information.
22
*/
23
uint32_t svc_imm;
24
- int aarch64;
25
int current_el;
26
/* Debug target exception level for single-step exceptions */
27
int debug_target_el;
28
GHashTable *cp_regs;
29
uint64_t features; /* CPU features bits */
30
+ bool aarch64;
31
/* Because unallocated encodings generate different exception syndrome
32
* information from traps due to FP being disabled, we can't do a single
33
* "is fp access disabled" check at a high level in the decode tree.
21
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
34
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
22
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/translate-a64.c
36
--- a/target/arm/translate-a64.c
24
+++ b/target/arm/translate-a64.c
37
+++ b/target/arm/translate-a64.c
25
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
38
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
26
39
dc->isar = &arm_cpu->isar;
27
case 2: /* complex fp */
40
dc->condjmp = 0;
28
/* Each indexable element is a complex pair. */
41
29
- size <<= 1;
42
- dc->aarch64 = 1;
30
+ size += 1;
43
+ dc->aarch64 = true;
31
switch (size) {
44
/* If we are coming from secure EL0 in a system with a 32-bit EL3, then
32
case MO_32:
45
* there is no secure EL1, so we route exceptions to EL3.
33
if (h && !is_q) {
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
*/
34
--
60
--
35
2.20.1
61
2.25.1
36
62
37
63
diff view generated by jsdifflib
1
From: Aaron Lindsay OS <aaron@os.amperecomputing.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Make PMU overflow interrupts more accurate by using a timer to predict
3
Bool is a more appropriate type for this value.
4
when they will overflow rather than waiting for an event to occur which
4
Adjust the assignments to use true/false.
5
allows us to otherwise check them.
6
5
7
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 20190124162401.5111-3-aaron@os.amperecomputing.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
9
---
12
target/arm/cpu.h | 10 +++++++
10
target/arm/cpu.h | 2 +-
13
target/arm/cpu.c | 12 ++++++++
11
target/arm/cpu.c | 2 +-
14
target/arm/helper.c | 72 +++++++++++++++++++++++++++++++++++++++++++--
12
target/arm/helper-a64.c | 4 ++--
15
3 files changed, 92 insertions(+), 2 deletions(-)
13
target/arm/helper.c | 2 +-
14
target/arm/hvf/hvf.c | 2 +-
15
5 files changed, 6 insertions(+), 6 deletions(-)
16
16
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
19
--- a/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
21
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
22
22
* all other bits are stored in their correct places in env->pstate
23
/* Timers used by the generic (architected) timer */
23
*/
24
QEMUTimer *gt_timer[NUM_GTIMERS];
24
uint32_t pstate;
25
+ /*
25
- uint32_t aarch64; /* 1 if CPU is in aarch64 state; inverse of PSTATE.nRW */
26
+ * Timer used by the PMU. Its state is restored after migration by
26
+ bool aarch64; /* True if CPU is in aarch64 state; inverse of PSTATE.nRW */
27
+ * pmu_op_finish() - it does not need other handling during migration
27
28
+ */
28
/* Cached TBFLAGS state. See below for which bits are included. */
29
+ QEMUTimer *pmu_timer;
29
CPUARMTBFlags hflags;
30
/* GPIO outputs for generic timer */
31
qemu_irq gt_timer_outputs[NUM_GTIMERS];
32
/* GPIO output for GICv3 maintenance interrupt signal */
33
@@ -XXX,XX +XXX,XX @@ void pmccntr_op_finish(CPUARMState *env);
34
void pmu_op_start(CPUARMState *env);
35
void pmu_op_finish(CPUARMState *env);
36
37
+/*
38
+ * Called when a PMU counter is due to overflow
39
+ */
40
+void arm_pmu_timer_cb(void *opaque);
41
+
42
/**
43
* Functions to register as EL change hooks for PMU mode filtering
44
*/
45
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
46
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/cpu.c
32
--- a/target/arm/cpu.c
48
+++ b/target/arm/cpu.c
33
+++ b/target/arm/cpu.c
49
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_finalizefn(Object *obj)
34
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
50
QLIST_REMOVE(hook, node);
35
51
g_free(hook);
36
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
52
}
37
/* 64 bit CPUs always start in 64 bit mode */
53
+#ifndef CONFIG_USER_ONLY
38
- env->aarch64 = 1;
54
+ if (cpu->pmu_timer) {
39
+ env->aarch64 = true;
55
+ timer_del(cpu->pmu_timer);
40
#if defined(CONFIG_USER_ONLY)
56
+ timer_deinit(cpu->pmu_timer);
41
env->pstate = PSTATE_MODE_EL0t;
57
+ timer_free(cpu->pmu_timer);
42
/* Userspace expects access to DC ZVA, CTL_EL0 and the cache ops */
58
+ }
43
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
59
+#endif
44
index XXXXXXX..XXXXXXX 100644
60
}
45
--- a/target/arm/helper-a64.c
61
46
+++ b/target/arm/helper-a64.c
62
static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
47
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
63
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
48
qemu_mutex_unlock_iothread();
64
arm_register_pre_el_change_hook(cpu, &pmu_pre_el_change, 0);
49
65
arm_register_el_change_hook(cpu, &pmu_post_el_change, 0);
50
if (!return_to_aa64) {
66
}
51
- env->aarch64 = 0;
67
+
52
+ env->aarch64 = false;
68
+#ifndef CONFIG_USER_ONLY
53
/* We do a raw CPSR write because aarch64_sync_64_to_32()
69
+ cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, arm_pmu_timer_cb,
54
* will sort the register banks out for us, and we've already
70
+ cpu);
55
* caught all the bad-mode cases in el_from_spsr().
71
+#endif
56
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
72
} else {
57
} else {
73
cpu->id_aa64dfr0 &= ~0xf00;
58
int tbii;
74
cpu->pmceid0 = 0;
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)) {
75
diff --git a/target/arm/helper.c b/target/arm/helper.c
65
diff --git a/target/arm/helper.c b/target/arm/helper.c
76
index XXXXXXX..XXXXXXX 100644
66
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/helper.c
67
--- a/target/arm/helper.c
78
+++ b/target/arm/helper.c
68
+++ b/target/arm/helper.c
79
@@ -XXX,XX +XXX,XX @@ typedef struct pm_event {
69
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
80
* counters hold a difference from the return value from this function
81
*/
82
uint64_t (*get_count)(CPUARMState *);
83
+ /*
84
+ * Return how many nanoseconds it will take (at a minimum) for count events
85
+ * to occur. A negative value indicates the counter will never overflow, or
86
+ * that the counter has otherwise arranged for the overflow bit to be set
87
+ * and the PMU interrupt to be raised on overflow.
88
+ */
89
+ int64_t (*ns_per_count)(uint64_t);
90
} pm_event;
91
92
static bool event_always_supported(CPUARMState *env)
93
@@ -XXX,XX +XXX,XX @@ static uint64_t swinc_get_count(CPUARMState *env)
94
return 0;
95
}
96
97
+static int64_t swinc_ns_per(uint64_t ignored)
98
+{
99
+ return -1;
100
+}
101
+
102
/*
103
* Return the underlying cycle count for the PMU cycle counters. If we're in
104
* usermode, simply return 0.
105
@@ -XXX,XX +XXX,XX @@ static uint64_t cycles_get_count(CPUARMState *env)
106
}
107
108
#ifndef CONFIG_USER_ONLY
109
+static int64_t cycles_ns_per(uint64_t cycles)
110
+{
111
+ return (ARM_CPU_FREQ / NANOSECONDS_PER_SECOND) * cycles;
112
+}
113
+
114
static bool instructions_supported(CPUARMState *env)
115
{
116
return use_icount == 1 /* Precise instruction counting */;
117
@@ -XXX,XX +XXX,XX @@ static uint64_t instructions_get_count(CPUARMState *env)
118
{
119
return (uint64_t)cpu_get_icount_raw();
120
}
121
+
122
+static int64_t instructions_ns_per(uint64_t icount)
123
+{
124
+ return cpu_icount_to_ns((int64_t)icount);
125
+}
126
#endif
127
128
static const pm_event pm_events[] = {
129
{ .number = 0x000, /* SW_INCR */
130
.supported = event_always_supported,
131
.get_count = swinc_get_count,
132
+ .ns_per_count = swinc_ns_per,
133
},
134
#ifndef CONFIG_USER_ONLY
135
{ .number = 0x008, /* INST_RETIRED, Instruction architecturally executed */
136
.supported = instructions_supported,
137
.get_count = instructions_get_count,
138
+ .ns_per_count = instructions_ns_per,
139
},
140
{ .number = 0x011, /* CPU_CYCLES, Cycle */
141
.supported = event_always_supported,
142
.get_count = cycles_get_count,
143
+ .ns_per_count = cycles_ns_per,
144
}
70
}
145
#endif
71
146
};
72
pstate_write(env, PSTATE_DAIF | new_mode);
147
@@ -XXX,XX +XXX,XX @@ void pmccntr_op_start(CPUARMState *env)
73
- env->aarch64 = 1;
148
void pmccntr_op_finish(CPUARMState *env)
74
+ env->aarch64 = true;
149
{
75
aarch64_restore_sp(env, new_el);
150
if (pmu_counter_enabled(env, 31)) {
76
helper_rebuild_hflags_a64(env, new_el);
151
- uint64_t prev_cycles = env->cp15.c15_ccnt_delta;
77
152
+#ifndef CONFIG_USER_ONLY
78
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
153
+ /* Calculate when the counter will next overflow */
79
index XXXXXXX..XXXXXXX 100644
154
+ uint64_t remaining_cycles = -env->cp15.c15_ccnt;
80
--- a/target/arm/hvf/hvf.c
155
+ if (!(env->cp15.c9_pmcr & PMCRLC)) {
81
+++ b/target/arm/hvf/hvf.c
156
+ remaining_cycles = (uint32_t)remaining_cycles;
82
@@ -XXX,XX +XXX,XX @@ int hvf_arch_init_vcpu(CPUState *cpu)
157
+ }
83
hv_return_t ret;
158
+ int64_t overflow_in = cycles_ns_per(remaining_cycles);
84
int i;
159
85
160
+ if (overflow_in > 0) {
86
- env->aarch64 = 1;
161
+ int64_t overflow_at = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
87
+ env->aarch64 = true;
162
+ overflow_in;
88
asm volatile("mrs %0, cntfrq_el0" : "=r"(arm_cpu->gt_cntfrq_hz));
163
+ ARMCPU *cpu = arm_env_get_cpu(env);
89
164
+ timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at);
90
/* Allocate enough space for our sysreg sync */
165
+ }
166
+#endif
167
+
168
+ uint64_t prev_cycles = env->cp15.c15_ccnt_delta;
169
if (env->cp15.c9_pmcr & PMCRD) {
170
/* Increment once every 64 processor clock cycles */
171
prev_cycles /= 64;
172
}
173
-
174
env->cp15.c15_ccnt_delta = prev_cycles - env->cp15.c15_ccnt;
175
}
176
}
177
@@ -XXX,XX +XXX,XX @@ static void pmevcntr_op_start(CPUARMState *env, uint8_t counter)
178
static void pmevcntr_op_finish(CPUARMState *env, uint8_t counter)
179
{
180
if (pmu_counter_enabled(env, counter)) {
181
+#ifndef CONFIG_USER_ONLY
182
+ uint16_t event = env->cp15.c14_pmevtyper[counter] & PMXEVTYPER_EVTCOUNT;
183
+ uint16_t event_idx = supported_event_map[event];
184
+ uint64_t delta = UINT32_MAX -
185
+ (uint32_t)env->cp15.c14_pmevcntr[counter] + 1;
186
+ int64_t overflow_in = pm_events[event_idx].ns_per_count(delta);
187
+
188
+ if (overflow_in > 0) {
189
+ int64_t overflow_at = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
190
+ overflow_in;
191
+ ARMCPU *cpu = arm_env_get_cpu(env);
192
+ timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at);
193
+ }
194
+#endif
195
+
196
env->cp15.c14_pmevcntr_delta[counter] -=
197
env->cp15.c14_pmevcntr[counter];
198
}
199
@@ -XXX,XX +XXX,XX @@ void pmu_post_el_change(ARMCPU *cpu, void *ignored)
200
pmu_op_finish(&cpu->env);
201
}
202
203
+void arm_pmu_timer_cb(void *opaque)
204
+{
205
+ ARMCPU *cpu = opaque;
206
+
207
+ /*
208
+ * Update all the counter values based on the current underlying counts,
209
+ * triggering interrupts to be raised, if necessary. pmu_op_finish() also
210
+ * has the effect of setting the cpu->pmu_timer to the next earliest time a
211
+ * counter may expire.
212
+ */
213
+ pmu_op_start(&cpu->env);
214
+ pmu_op_finish(&cpu->env);
215
+}
216
+
217
static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
218
uint64_t value)
219
{
220
--
91
--
221
2.20.1
92
2.25.1
222
93
223
94
diff view generated by jsdifflib
1
The "system instructions" and "system register move" subcategories
1
From: Richard Henderson <richard.henderson@linaro.org>
2
of "branches, exception generating and system instructions" for A64
3
only apply if bits [23:22] are zero; other values are currently
4
unallocated. Correctly UNDEF these unallocated encodings.
5
2
6
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
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()]
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
9
Message-id: 20190125182626.9221-2-peter.maydell@linaro.org
10
---
10
---
11
target/arm/translate-a64.c | 6 +++++-
11
target/arm/translate-a32.h | 13 +++++--------
12
1 file changed, 5 insertions(+), 1 deletion(-)
12
target/arm/translate.c | 21 ++++++++++++++++++++-
13
2 files changed, 25 insertions(+), 9 deletions(-)
13
14
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-a64.c
17
--- a/target/arm/translate-a32.h
17
+++ b/target/arm/translate-a64.c
18
+++ b/target/arm/translate-a32.h
18
@@ -XXX,XX +XXX,XX @@ static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ static inline TCGv_i32 load_cpu_offset(int offset)
19
break;
20
20
case 0x6a: /* Exception generation / System */
21
#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
21
if (insn & (1 << 24)) {
22
22
- disas_system(s, insn);
23
-static inline void store_cpu_offset(TCGv_i32 var, int offset)
23
+ if (extract32(insn, 22, 2) == 0) {
24
-{
24
+ disas_system(s, insn);
25
- tcg_gen_st_i32(var, cpu_env, offset);
25
+ } else {
26
- tcg_temp_free_i32(var);
26
+ unallocated_encoding(s);
27
-}
27
+ }
28
+void store_cpu_offset(TCGv_i32 var, int offset, int size);
28
} else {
29
29
disas_exc(s, insn);
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
}
30
}
80
}
31
--
81
--
32
2.20.1
82
2.25.1
33
34
diff view generated by jsdifflib
1
From: Remi Denis-Courmont <remi.denis.courmont@huawei.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
A flawed test lead to the instructions always being treated as
3
Bool is a more appropriate type for this value.
4
unallocated encodings.
4
Move the member down in the struct to keep the
5
bool type members together and remove a hole.
5
6
6
Fixes: https://bugs.launchpad.net/bugs/1813460
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Remi Denis-Courmont <remi.denis.courmont@huawei.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
target/arm/translate.h | 2 +-
11
target/arm/translate-a64.c | 2 +-
12
target/arm/translate-a64.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
2 files changed, 2 insertions(+), 2 deletions(-)
13
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.
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
35
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-a64.c
37
--- a/target/arm/translate-a64.c
17
+++ b/target/arm/translate-a64.c
38
+++ b/target/arm/translate-a64.c
18
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
39
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
19
if (!dc_isar_feature(aa64_pauth, s)) {
40
*/
20
goto do_unallocated;
41
dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
21
}
42
!arm_el_is_aa64(env, 3);
22
- if (op3 != 2 || op3 != 3) {
43
- dc->thumb = 0;
23
+ if ((op3 & ~1) != 2) {
44
+ dc->thumb = false;
24
goto do_unallocated;
45
dc->sctlr_b = 0;
25
}
46
dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE;
26
if (s->pauth_active) {
47
dc->condexec_mask = 0;
27
--
48
--
28
2.20.1
49
2.25.1
29
30
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Drop the pac properties. This approach cannot work as written
3
Bool is a more appropriate type for this value.
4
because the properties are applied before arm_cpu_reset, which
4
Adjust the assignments to use true/false.
5
zeros SCTLR_EL1 (amongst everything else).
6
5
7
We can re-introduce the properties if they turn out to be useful.
8
But since linux 5.0 enables all of the keys, they may not be.
9
10
Fixes: 1ae9cfbd470
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
9
---
15
target/arm/cpu.c | 3 +++
10
target/arm/cpu.h | 2 +-
16
target/arm/cpu64.c | 60 ----------------------------------------------
11
linux-user/arm/cpu_loop.c | 2 +-
17
2 files changed, 3 insertions(+), 60 deletions(-)
12
target/arm/cpu.c | 2 +-
13
target/arm/m_helper.c | 6 +++---
14
4 files changed, 6 insertions(+), 6 deletions(-)
18
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;
19
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
49
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
20
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.c
51
--- a/target/arm/cpu.c
22
+++ b/target/arm/cpu.c
52
+++ b/target/arm/cpu.c
23
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
53
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_set_pc(CPUState *cs, vaddr value)
24
env->pstate = PSTATE_MODE_EL0t;
54
25
/* Userspace expects access to DC ZVA, CTL_EL0 and the cache ops */
55
if (is_a64(env)) {
26
env->cp15.sctlr_el[1] |= SCTLR_UCT | SCTLR_UCI | SCTLR_DZE;
56
env->pc = value;
27
+ /* Enable all PAC keys. */
57
- env->thumb = 0;
28
+ env->cp15.sctlr_el[1] |= (SCTLR_EnIA | SCTLR_EnIB |
58
+ env->thumb = false;
29
+ SCTLR_EnDA | SCTLR_EnDB);
59
} else {
30
/* Enable all PAC instructions */
60
env->regs[15] = value & ~1;
31
env->cp15.hcr_el2 |= HCR_API;
61
env->thumb = value & 1;
32
env->cp15.scr_el3 |= SCR_API;
62
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
33
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
34
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/cpu64.c
64
--- a/target/arm/m_helper.c
36
+++ b/target/arm/cpu64.c
65
+++ b/target/arm/m_helper.c
37
@@ -XXX,XX +XXX,XX @@ static void cpu_max_set_sve_vq(Object *obj, Visitor *v, const char *name,
66
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest)
38
error_propagate(errp, err);
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);
39
}
74
}
40
75
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
41
-#ifdef CONFIG_USER_ONLY
76
* except that the low bit doesn't indicate Thumb/not.
42
-static void cpu_max_get_packey(Object *obj, Visitor *v, const char *name,
43
- void *opaque, Error **errp)
44
-{
45
- ARMCPU *cpu = ARM_CPU(obj);
46
- const uint64_t *bit = opaque;
47
- bool enabled = (cpu->env.cp15.sctlr_el[1] & *bit) != 0;
48
-
49
- visit_type_bool(v, name, &enabled, errp);
50
-}
51
-
52
-static void cpu_max_set_packey(Object *obj, Visitor *v, const char *name,
53
- void *opaque, Error **errp)
54
-{
55
- ARMCPU *cpu = ARM_CPU(obj);
56
- Error *err = NULL;
57
- const uint64_t *bit = opaque;
58
- bool enabled;
59
-
60
- visit_type_bool(v, name, &enabled, errp);
61
-
62
- if (!err) {
63
- if (enabled) {
64
- cpu->env.cp15.sctlr_el[1] |= *bit;
65
- } else {
66
- cpu->env.cp15.sctlr_el[1] &= ~*bit;
67
- }
68
- }
69
- error_propagate(errp, err);
70
-}
71
-#endif
72
-
73
/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host);
74
* otherwise, a CPU with as many features enabled as our emulation supports.
75
* The version of '-cpu max' for qemu-system-arm is defined in cpu.c;
76
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
77
*/
77
*/
78
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
78
env->regs[14] = nextinst;
79
cpu->dcz_blocksize = 7; /* 512 bytes */
79
- env->thumb = 1;
80
-
80
+ env->thumb = true;
81
- /*
81
env->regs[15] = dest & ~1;
82
- * Note that Linux will enable enable all of the keys at once.
82
return;
83
- * But doing it this way will allow experimentation beyond that.
83
}
84
- */
84
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
85
- {
85
}
86
- static const uint64_t apia_bit = SCTLR_EnIA;
86
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
87
- static const uint64_t apib_bit = SCTLR_EnIB;
87
switch_v7m_security_state(env, 0);
88
- static const uint64_t apda_bit = SCTLR_EnDA;
88
- env->thumb = 1;
89
- static const uint64_t apdb_bit = SCTLR_EnDB;
89
+ env->thumb = true;
90
-
90
env->regs[15] = dest;
91
- object_property_add(obj, "apia", "bool", cpu_max_get_packey,
91
arm_rebuild_hflags(env);
92
- cpu_max_set_packey, NULL,
92
}
93
- (void *)&apia_bit, &error_fatal);
94
- object_property_add(obj, "apib", "bool", cpu_max_get_packey,
95
- cpu_max_set_packey, NULL,
96
- (void *)&apib_bit, &error_fatal);
97
- object_property_add(obj, "apda", "bool", cpu_max_get_packey,
98
- cpu_max_set_packey, NULL,
99
- (void *)&apda_bit, &error_fatal);
100
- object_property_add(obj, "apdb", "bool", cpu_max_get_packey,
101
- cpu_max_set_packey, NULL,
102
- (void *)&apdb_bit, &error_fatal);
103
-
104
- /* Enable all PAC keys by default. */
105
- cpu->env.cp15.sctlr_el[1] |= SCTLR_EnIA | SCTLR_EnIB;
106
- cpu->env.cp15.sctlr_el[1] |= SCTLR_EnDA | SCTLR_EnDB;
107
- }
108
#endif
109
110
cpu->sve_max_vq = ARM_MAX_VQ;
111
--
93
--
112
2.20.1
94
2.25.1
113
114
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
These bits become writable with the ARMv8.3-PAuth extension.
3
This function is incorrect in that it does not properly consider
4
CPTR_EL2.FPEN. We've already got another mechanism for raising
5
an FPU access trap: ARM_CP_FPU, so use that instead.
6
7
Remove CP_ACCESS_TRAP_FP_EL{2,3}, which becomes unused.
4
8
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20190129143511.12311-1-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
12
---
10
target/arm/helper.c | 6 ++++++
13
target/arm/cpu.h | 5 -----
11
1 file changed, 6 insertions(+)
14
target/arm/helper.c | 17 ++---------------
15
target/arm/op_helper.c | 13 -------------
16
3 files changed, 2 insertions(+), 33 deletions(-)
12
17
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
21
+++ b/target/arm/cpu.h
22
@@ -XXX,XX +XXX,XX @@ typedef enum CPAccessResult {
23
/* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
24
CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
25
CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
26
- /* Access fails and results in an exception syndrome for an FP access,
27
- * trapped directly to EL2 or EL3
28
- */
29
- CP_ACCESS_TRAP_FP_EL2 = 7,
30
- CP_ACCESS_TRAP_FP_EL3 = 8,
31
} CPAccessResult;
32
33
/* Access functions for coprocessor registers. These cannot fail and
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
34
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
36
--- a/target/arm/helper.c
16
+++ b/target/arm/helper.c
37
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
38
@@ -XXX,XX +XXX,XX @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
18
if (cpu_isar_feature(aa64_lor, cpu)) {
19
valid_mask |= SCR_TLOR;
20
}
39
}
21
+ if (cpu_isar_feature(aa64_pauth, cpu)) {
40
}
22
+ valid_mask |= SCR_API | SCR_APK;
41
23
+ }
42
-static CPAccessResult fpexc32_access(CPUARMState *env, const ARMCPRegInfo *ri,
24
43
- bool isread)
25
/* Clear all-context RES0 bits. */
44
-{
26
value &= valid_mask;
45
- if ((env->cp15.cptr_el[2] & CPTR_TFP) && arm_current_el(env) == 2) {
27
@@ -XXX,XX +XXX,XX @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
46
- return CP_ACCESS_TRAP_FP_EL2;
28
if (cpu_isar_feature(aa64_lor, cpu)) {
47
- }
29
valid_mask |= HCR_TLOR;
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();
30
}
92
}
31
+ if (cpu_isar_feature(aa64_pauth, cpu)) {
32
+ valid_mask |= HCR_API | HCR_APK;
33
+ }
34
35
/* Clear RES0 bits. */
36
value &= valid_mask;
37
--
93
--
38
2.20.1
94
2.25.1
39
40
diff view generated by jsdifflib
1
The FCMLA (by element) instruction exists in the
1
From: Richard Henderson <richard.henderson@linaro.org>
2
"vector x indexed element" encoding group, but not in
3
the "scalar x indexed element" group. Correctly UNDEF
4
the unallocated encodings.
5
2
6
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
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>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
9
Message-id: 20190129140411.682-2-peter.maydell@linaro.org
10
---
9
---
11
target/arm/translate-a64.c | 2 +-
10
target/arm/translate-a64.c | 25 ++++++++++++-------------
12
1 file changed, 1 insertion(+), 1 deletion(-)
11
1 file changed, 12 insertions(+), 13 deletions(-)
13
12
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-a64.c
15
--- a/target/arm/translate-a64.c
17
+++ b/target/arm/translate-a64.c
16
+++ b/target/arm/translate-a64.c
18
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
17
@@ -XXX,XX +XXX,XX @@ static int get_a64_user_mem_index(DisasContext *s)
19
case 0x13: /* FCMLA #90 */
18
return arm_to_core_mmu_idx(useridx);
20
case 0x15: /* FCMLA #180 */
19
}
21
case 0x17: /* FCMLA #270 */
20
22
- if (!dc_isar_feature(aa64_fcma, s)) {
21
-static void reset_btype(DisasContext *s)
23
+ if (is_scalar || !dc_isar_feature(aa64_fcma, s)) {
22
+static void set_btype_raw(int val)
24
unallocated_encoding(s);
23
{
25
return;
24
- if (s->btype != 0) {
26
}
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);
27
--
59
--
28
2.20.1
60
2.25.1
29
30
diff view generated by jsdifflib
1
In the AdvSIMD scalar x indexed element and vector x indexed element
1
From: Richard Henderson <richard.henderson@linaro.org>
2
encoding group, the SDOT and UDOT instructions are vector only,
3
and their opcode is unallocated in the scalar group. Correctly
4
UNDEF this unallocated encoding.
5
2
6
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
3
For aa32, the function has a parameter to use the new el.
4
For aa64, that never happens.
5
Use tcg_constant_i32 while we're at it.
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
9
Message-id: 20190125182626.9221-8-peter.maydell@linaro.org
10
---
10
---
11
target/arm/translate-a64.c | 2 +-
11
target/arm/translate-a64.c | 21 +++++++++-----------
12
1 file changed, 1 insertion(+), 1 deletion(-)
12
target/arm/translate.c | 40 +++++++++++++++++++++++---------------
13
2 files changed, 33 insertions(+), 28 deletions(-)
13
14
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-a64.c
17
--- a/target/arm/translate-a64.c
17
+++ b/target/arm/translate-a64.c
18
+++ b/target/arm/translate-a64.c
18
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ static void a64_free_cc(DisasCompare64 *c64)
20
tcg_temp_free_i64(c64->value);
21
}
22
23
+static void gen_rebuild_hflags(DisasContext *s)
24
+{
25
+ gen_helper_rebuild_hflags_a64(cpu_env, tcg_constant_i32(s->current_el));
26
+}
27
+
28
static void gen_exception_internal(int excp)
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);
19
break;
39
break;
20
case 0x0e: /* SDOT */
40
21
case 0x1e: /* UDOT */
41
case 0x04: /* PAN */
22
- if (size != MO_32 || !dc_isar_feature(aa64_dp, s)) {
42
@@ -XXX,XX +XXX,XX @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
23
+ if (is_scalar || size != MO_32 || !dc_isar_feature(aa64_dp, s)) {
43
} else {
24
unallocated_encoding(s);
44
clear_pstate_bits(PSTATE_PAN);
25
return;
26
}
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
+{
85
+ bool m_profile = arm_dc_feature(s, ARM_FEATURE_M);
86
+
87
+ if (new_el) {
88
+ if (m_profile) {
89
+ gen_helper_rebuild_hflags_m32_newel(cpu_env);
90
+ } else {
91
+ gen_helper_rebuild_hflags_a32_newel(cpu_env);
92
+ }
93
+ } else {
94
+ TCGv_i32 tcg_el = tcg_constant_i32(s->current_el);
95
+ if (m_profile) {
96
+ gen_helper_rebuild_hflags_m32(cpu_env, tcg_el);
97
+ } else {
98
+ gen_helper_rebuild_hflags_a32(cpu_env, tcg_el);
99
+ }
100
+ }
101
+}
102
+
103
static void gen_exception_internal(int excp)
104
{
105
TCGv_i32 tcg_excp = tcg_const_i32(excp);
106
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
107
* A write to any coprocessor register that ends a TB
108
* must rebuild the hflags for the next TB.
109
*/
110
- TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
111
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
112
- gen_helper_rebuild_hflags_m32(cpu_env, tcg_el);
113
- } else {
114
- if (ri->type & ARM_CP_NEWEL) {
115
- gen_helper_rebuild_hflags_a32_newel(cpu_env);
116
- } else {
117
- gen_helper_rebuild_hflags_a32(cpu_env, tcg_el);
118
- }
119
- }
120
- tcg_temp_free_i32(tcg_el);
121
+ gen_rebuild_hflags(s, ri->type & ARM_CP_NEWEL);
122
/*
123
* We default to ending the TB on a coprocessor register write,
124
* but allow this to be suppressed by the register definition
125
@@ -XXX,XX +XXX,XX @@ static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
126
tcg_temp_free_i32(addr);
127
tcg_temp_free_i32(reg);
128
/* If we wrote to CONTROL, the EL might have changed */
129
- gen_helper_rebuild_hflags_m32_newel(cpu_env);
130
+ gen_rebuild_hflags(s, true);
131
gen_lookup_tb(s);
132
return true;
133
}
134
@@ -XXX,XX +XXX,XX @@ static bool trans_CPS(DisasContext *s, arg_CPS *a)
135
136
static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a)
137
{
138
- TCGv_i32 tmp, addr, el;
139
+ TCGv_i32 tmp, addr;
140
141
if (!arm_dc_feature(s, ARM_FEATURE_M)) {
142
return false;
143
@@ -XXX,XX +XXX,XX @@ static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a)
144
gen_helper_v7m_msr(cpu_env, addr, tmp);
145
tcg_temp_free_i32(addr);
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;
27
--
154
--
28
2.20.1
155
2.25.1
29
30
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
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
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Use tcg_gen_umin_i32 instead of tcg_gen_movcond_i32.
4
Use tcg_constant_i32 while we're at it.
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.c | 8 +++-----
11
1 file changed, 3 insertions(+), 5 deletions(-)
12
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
16
+++ b/target/arm/translate.c
17
@@ -XXX,XX +XXX,XX @@ GEN_SHIFT(shr)
18
19
static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
20
{
21
- TCGv_i32 tmp1, tmp2;
22
- tmp1 = tcg_temp_new_i32();
23
+ TCGv_i32 tmp1 = tcg_temp_new_i32();
24
+
25
tcg_gen_andi_i32(tmp1, t1, 0xff);
26
- tmp2 = tcg_const_i32(0x1f);
27
- tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
28
- tcg_temp_free_i32(tmp2);
29
+ tcg_gen_umin_i32(tmp1, tmp1, tcg_constant_i32(31));
30
tcg_gen_sar_i32(dest, t0, tmp1);
31
tcg_temp_free_i32(tmp1);
32
}
33
--
34
2.25.1
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
The length of the previous insn may be computed from
4
the difference of start and end addresses.
5
Use tcg_constant_i32 while we're at it.
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.c | 12 ++++--------
12
1 file changed, 4 insertions(+), 8 deletions(-)
13
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate.c
17
+++ b/target/arm/translate.c
18
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
19
/* nothing more to generate */
20
break;
21
case DISAS_WFI:
22
- {
23
- TCGv_i32 tmp = tcg_const_i32((dc->thumb &&
24
- !(dc->insn & (1U << 31))) ? 2 : 4);
25
-
26
- gen_helper_wfi(cpu_env, tmp);
27
- tcg_temp_free_i32(tmp);
28
- /* The helper doesn't necessarily throw an exception, but we
29
+ gen_helper_wfi(cpu_env,
30
+ tcg_constant_i32(dc->base.pc_next - dc->pc_curr));
31
+ /*
32
+ * The helper doesn't necessarily throw an exception, but we
33
* must go back to the main loop to check for interrupts anyway.
34
*/
35
tcg_gen_exit_tb(NULL, 0);
36
break;
37
- }
38
case DISAS_WFE:
39
gen_helper_wfe(cpu_env);
40
break;
41
--
42
2.25.1
diff view generated by jsdifflib
1
From: Julia Suvorova <jusual@mail.ru>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Until now, the set_pc logic was unclear, which raised questions about
3
Use tcg_constant_{i32,i64} as appropriate throughout.
4
whether it should be used directly, applying a value to PC or adding
4
This fixes a bug in trans_VSCCLRM() where we were leaking a TCGv.
5
additional checks, for example, set the Thumb bit in Arm cpu. Let's set
6
the set_pc logic for “Configure the PC, as was done in the ELF file”
7
and implement synchronize_with_tb hook for preserving PC to cpu_tb_exec.
8
5
9
Signed-off-by: Julia Suvorova <jusual@mail.ru>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Message-id: 20190129121817.7109-1-jusual@mail.ru
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
9
---
15
include/qom/cpu.h | 16 ++++++++++++++--
10
target/arm/translate-m-nocp.c | 12 +++++-------
16
hw/arm/boot.c | 4 ----
11
1 file changed, 5 insertions(+), 7 deletions(-)
17
target/arm/arm-powerctl.c | 3 ---
18
target/arm/cpu.c | 26 +++++++++++++++++++++++++-
19
target/arm/cpu64.c | 15 ---------------
20
5 files changed, 39 insertions(+), 25 deletions(-)
21
12
22
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
13
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
23
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
24
--- a/include/qom/cpu.h
15
--- a/target/arm/translate-m-nocp.c
25
+++ b/include/qom/cpu.h
16
+++ b/target/arm/translate-m-nocp.c
26
@@ -XXX,XX +XXX,XX @@ struct TranslationBlock;
17
@@ -XXX,XX +XXX,XX @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
27
* @get_arch_id: Callback for getting architecture-dependent CPU ID.
28
* @get_paging_enabled: Callback for inquiring whether paging is enabled.
29
* @get_memory_mapping: Callback for obtaining the memory mappings.
30
- * @set_pc: Callback for setting the Program Counter register.
31
+ * @set_pc: Callback for setting the Program Counter register. This
32
+ * should have the semantics used by the target architecture when
33
+ * setting the PC from a source such as an ELF file entry point;
34
+ * for example on Arm it will also set the Thumb mode bit based
35
+ * on the least significant bit of the new PC value.
36
+ * If the target behaviour here is anything other than "set
37
+ * the PC register to the value passed in" then the target must
38
+ * also implement the synchronize_from_tb hook.
39
* @synchronize_from_tb: Callback for synchronizing state from a TCG
40
- * #TranslationBlock.
41
+ * #TranslationBlock. This is called when we abandon execution
42
+ * of a TB before starting it, and must set all parts of the CPU
43
+ * state which the previous TB in the chain may not have updated.
44
+ * This always includes at least the program counter; some targets
45
+ * will need to do more. If this hook is not implemented then the
46
+ * default is to call @set_pc(tb->pc).
47
* @handle_mmu_fault: Callback for handling an MMU fault.
48
* @get_phys_page_debug: Callback for obtaining a physical address.
49
* @get_phys_page_attrs_debug: Callback for obtaining a physical address and the
50
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/arm/boot.c
53
+++ b/hw/arm/boot.c
54
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
55
g_assert_not_reached();
56
}
57
58
- if (!env->aarch64) {
59
- env->thumb = info->entry & 1;
60
- entry &= 0xfffffffe;
61
- }
62
cpu_set_pc(cs, entry);
63
} else {
64
/* If we are booting Linux then we need to check whether we are
65
diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/arm-powerctl.c
68
+++ b/target/arm/arm-powerctl.c
69
@@ -XXX,XX +XXX,XX @@ static void arm_set_cpu_on_async_work(CPUState *target_cpu_state,
70
71
if (info->target_aa64) {
72
target_cpu->env.xregs[0] = info->context_id;
73
- target_cpu->env.thumb = false;
74
} else {
75
target_cpu->env.regs[0] = info->context_id;
76
- target_cpu->env.thumb = info->entry & 1;
77
- info->entry &= 0xfffffffe;
78
}
18
}
79
19
80
/* Start the new CPU at the requested address */
20
/* Zero the Sregs from btmreg to topreg inclusive. */
81
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
- zero = tcg_const_i64(0);
82
index XXXXXXX..XXXXXXX 100644
22
+ zero = tcg_constant_i64(0);
83
--- a/target/arm/cpu.c
23
if (btmreg & 1) {
84
+++ b/target/arm/cpu.c
24
write_neon_element64(zero, btmreg >> 1, 1, MO_32);
85
@@ -XXX,XX +XXX,XX @@
25
btmreg++;
86
static void arm_cpu_set_pc(CPUState *cs, vaddr value)
26
@@ -XXX,XX +XXX,XX @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
87
{
27
}
88
ARMCPU *cpu = ARM_CPU(cs);
28
assert(btmreg == topreg + 1);
89
+ CPUARMState *env = &cpu->env;
29
if (dc_isar_feature(aa32_mve, s)) {
90
30
- TCGv_i32 z32 = tcg_const_i32(0);
91
- cpu->env.regs[15] = value;
31
- store_cpu_field(z32, v7m.vpr);
92
+ if (is_a64(env)) {
32
+ store_cpu_field(tcg_constant_i32(0), v7m.vpr);
93
+ env->pc = value;
33
}
94
+ env->thumb = 0;
34
95
+ } else {
35
clear_eci_state(s);
96
+ env->regs[15] = value & ~1;
36
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
97
+ env->thumb = value & 1;
37
}
98
+ }
38
case ARM_VFP_FPCXT_NS:
99
+}
39
{
100
+
40
- TCGv_i32 control, sfpa, fpscr, fpdscr, zero;
101
+static void arm_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
41
+ TCGv_i32 control, sfpa, fpscr, fpdscr;
102
+{
42
TCGLabel *lab_active = gen_new_label();
103
+ ARMCPU *cpu = ARM_CPU(cs);
43
104
+ CPUARMState *env = &cpu->env;
44
lookup_tb = true;
105
+
45
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
106
+ /*
46
storefn(s, opaque, tmp, true);
107
+ * It's OK to look at env for the current mode here, because it's
47
/* If SFPA is zero then set FPSCR from FPDSCR_NS */
108
+ * never possible for an AArch64 TB to chain to an AArch32 TB.
48
fpdscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
109
+ */
49
- zero = tcg_const_i32(0);
110
+ if (is_a64(env)) {
50
- tcg_gen_movcond_i32(TCG_COND_EQ, fpscr, sfpa, zero, fpdscr, fpscr);
111
+ env->pc = tb->pc;
51
+ tcg_gen_movcond_i32(TCG_COND_EQ, fpscr, sfpa, tcg_constant_i32(0),
112
+ } else {
52
+ fpdscr, fpscr);
113
+ env->regs[15] = tb->pc;
53
gen_helper_vfp_set_fpscr(cpu_env, fpscr);
114
+ }
54
- tcg_temp_free_i32(zero);
115
}
55
tcg_temp_free_i32(sfpa);
116
56
tcg_temp_free_i32(fpdscr);
117
static bool arm_cpu_has_work(CPUState *cs)
57
tcg_temp_free_i32(fpscr);
118
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
119
cc->cpu_exec_interrupt = arm_cpu_exec_interrupt;
120
cc->dump_state = arm_cpu_dump_state;
121
cc->set_pc = arm_cpu_set_pc;
122
+ cc->synchronize_from_tb = arm_cpu_synchronize_from_tb;
123
cc->gdb_read_register = arm_cpu_gdb_read_register;
124
cc->gdb_write_register = arm_cpu_gdb_write_register;
125
#ifdef CONFIG_USER_ONLY
126
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
127
index XXXXXXX..XXXXXXX 100644
128
--- a/target/arm/cpu64.c
129
+++ b/target/arm/cpu64.c
130
@@ -XXX,XX +XXX,XX @@ static void aarch64_cpu_finalizefn(Object *obj)
131
{
132
}
133
134
-static void aarch64_cpu_set_pc(CPUState *cs, vaddr value)
135
-{
136
- ARMCPU *cpu = ARM_CPU(cs);
137
- /* It's OK to look at env for the current mode here, because it's
138
- * never possible for an AArch64 TB to chain to an AArch32 TB.
139
- * (Otherwise we would need to use synchronize_from_tb instead.)
140
- */
141
- if (is_a64(&cpu->env)) {
142
- cpu->env.pc = value;
143
- } else {
144
- cpu->env.regs[15] = value;
145
- }
146
-}
147
-
148
static gchar *aarch64_gdb_arch_name(CPUState *cs)
149
{
150
return g_strdup("aarch64");
151
@@ -XXX,XX +XXX,XX @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
152
CPUClass *cc = CPU_CLASS(oc);
153
154
cc->cpu_exec_interrupt = arm_cpu_exec_interrupt;
155
- cc->set_pc = aarch64_cpu_set_pc;
156
cc->gdb_read_register = aarch64_cpu_gdb_read_register;
157
cc->gdb_write_register = aarch64_cpu_gdb_write_register;
158
cc->gdb_num_core_regs = 34;
159
--
58
--
160
2.20.1
59
2.25.1
161
162
diff view generated by jsdifflib
1
From: Aaron Lindsay OS <aaron@os.amperecomputing.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Whenever we notice that a counter overflow has occurred, send an
3
Use tcg_constant_{i32,i64} as appropriate throughout.
4
interrupt. This is made more reliable with the addition of a timer in a
5
follow-on commit.
6
4
7
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20190124162401.5111-2-aaron@os.amperecomputing.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
8
---
12
target/arm/helper.c | 61 +++++++++++++++++++++++++++++++++++++--------
9
target/arm/translate-neon.c | 21 +++++++--------------
13
1 file changed, 51 insertions(+), 10 deletions(-)
10
1 file changed, 7 insertions(+), 14 deletions(-)
14
11
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
diff --git a/target/arm/translate-neon.c b/target/arm/translate-neon.c
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
14
--- a/target/arm/translate-neon.c
18
+++ b/target/arm/helper.c
15
+++ b/target/arm/translate-neon.c
19
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
16
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a)
20
/* Definitions for the PMU registers */
17
int mmu_idx = get_mem_index(s);
21
#define PMCRN_MASK 0xf800
18
int size = a->size;
22
#define PMCRN_SHIFT 11
19
TCGv_i64 tmp64;
23
+#define PMCRLC 0x40
20
- TCGv_i32 addr, tmp;
24
#define PMCRDP 0x10
21
+ TCGv_i32 addr;
25
#define PMCRD 0x8
22
26
#define PMCRC 0x4
23
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
27
@@ -XXX,XX +XXX,XX @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter)
24
return false;
28
return enabled && !prohibited && !filtered;
25
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a)
29
}
26
30
27
tmp64 = tcg_temp_new_i64();
31
+static void pmu_update_irq(CPUARMState *env)
28
addr = tcg_temp_new_i32();
32
+{
29
- tmp = tcg_const_i32(1 << size);
33
+ ARMCPU *cpu = arm_env_get_cpu(env);
30
load_reg_var(s, addr, a->rn);
34
+ qemu_set_irq(cpu->pmu_interrupt, (env->cp15.c9_pmcr & PMCRE) &&
31
35
+ (env->cp15.c9_pminten & env->cp15.c9_pmovsr));
32
mop = endian | size | align;
36
+}
33
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a)
37
+
34
neon_load_element64(tmp64, tt, n, size);
38
/*
35
gen_aa32_st_internal_i64(s, tmp64, addr, mmu_idx, mop);
39
* Ensure c15_ccnt is the guest-visible count so that operations such as
36
}
40
* enabling/disabling the counter or filtering, modifying the count itself,
37
- tcg_gen_add_i32(addr, addr, tmp);
41
@@ -XXX,XX +XXX,XX @@ void pmccntr_op_start(CPUARMState *env)
38
+ tcg_gen_addi_i32(addr, addr, 1 << size);
42
eff_cycles /= 64;
39
43
}
40
/* Subsequent memory operations inherit alignment */
44
41
mop &= ~MO_AMASK;
45
- env->cp15.c15_ccnt = eff_cycles - env->cp15.c15_ccnt_delta;
42
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a)
46
+ uint64_t new_pmccntr = eff_cycles - env->cp15.c15_ccnt_delta;
47
+
48
+ uint64_t overflow_mask = env->cp15.c9_pmcr & PMCRLC ? \
49
+ 1ull << 63 : 1ull << 31;
50
+ if (env->cp15.c15_ccnt & ~new_pmccntr & overflow_mask) {
51
+ env->cp15.c9_pmovsr |= (1 << 31);
52
+ pmu_update_irq(env);
53
+ }
54
+
55
+ env->cp15.c15_ccnt = new_pmccntr;
56
}
57
env->cp15.c15_ccnt_delta = cycles;
58
}
59
@@ -XXX,XX +XXX,XX @@ static void pmevcntr_op_start(CPUARMState *env, uint8_t counter)
60
}
61
62
if (pmu_counter_enabled(env, counter)) {
63
- env->cp15.c14_pmevcntr[counter] =
64
- count - env->cp15.c14_pmevcntr_delta[counter];
65
+ uint32_t new_pmevcntr = count - env->cp15.c14_pmevcntr_delta[counter];
66
+
67
+ if (env->cp15.c14_pmevcntr[counter] & ~new_pmevcntr & INT32_MIN) {
68
+ env->cp15.c9_pmovsr |= (1 << counter);
69
+ pmu_update_irq(env);
70
+ }
71
+ env->cp15.c14_pmevcntr[counter] = new_pmevcntr;
72
}
73
env->cp15.c14_pmevcntr_delta[counter] = count;
74
}
75
@@ -XXX,XX +XXX,XX @@ static void pmswinc_write(CPUARMState *env, const ARMCPRegInfo *ri,
76
/* counter is SW_INCR */
77
(env->cp15.c14_pmevtyper[i] & PMXEVTYPER_EVTCOUNT) == 0x0) {
78
pmevcntr_op_start(env, i);
79
- env->cp15.c14_pmevcntr[i]++;
80
+
81
+ /*
82
+ * Detect if this write causes an overflow since we can't predict
83
+ * PMSWINC overflows like we can for other events
84
+ */
85
+ uint32_t new_pmswinc = env->cp15.c14_pmevcntr[i] + 1;
86
+
87
+ if (env->cp15.c14_pmevcntr[i] & ~new_pmswinc & INT32_MIN) {
88
+ env->cp15.c9_pmovsr |= (1 << i);
89
+ pmu_update_irq(env);
90
+ }
91
+
92
+ env->cp15.c14_pmevcntr[i] = new_pmswinc;
93
+
94
pmevcntr_op_finish(env, i);
95
}
43
}
96
}
44
}
97
@@ -XXX,XX +XXX,XX @@ static void pmovsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
45
tcg_temp_free_i32(addr);
98
{
46
- tcg_temp_free_i32(tmp);
99
value &= pmu_counter_mask(env);
47
tcg_temp_free_i64(tmp64);
100
env->cp15.c9_pmovsr &= ~value;
48
101
+ pmu_update_irq(env);
49
gen_neon_ldst_base_update(s, a->rm, a->rn, nregs * interleave * 8);
50
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_env_64(DisasContext *s, arg_2reg_shift *a,
51
* To avoid excessive duplication of ops we implement shift
52
* by immediate using the variable shift operations.
53
*/
54
- constimm = tcg_const_i64(dup_const(a->size, a->shift));
55
+ constimm = tcg_constant_i64(dup_const(a->size, a->shift));
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;
102
}
65
}
103
66
104
static void pmovsset_write(CPUARMState *env, const ARMCPRegInfo *ri,
67
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_env_32(DisasContext *s, arg_2reg_shift *a,
105
@@ -XXX,XX +XXX,XX @@ static void pmovsset_write(CPUARMState *env, const ARMCPRegInfo *ri,
68
* To avoid excessive duplication of ops we implement shift
106
{
69
* by immediate using the variable shift operations.
107
value &= pmu_counter_mask(env);
70
*/
108
env->cp15.c9_pmovsr |= value;
71
- constimm = tcg_const_i32(dup_const(a->size, a->shift));
109
+ pmu_update_irq(env);
72
+ constimm = tcg_constant_i32(dup_const(a->size, a->shift));
73
tmp = tcg_temp_new_i32();
74
75
for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
76
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_env_32(DisasContext *s, arg_2reg_shift *a,
77
write_neon_element32(tmp, a->vd, pass, MO_32);
78
}
79
tcg_temp_free_i32(tmp);
80
- tcg_temp_free_i32(constimm);
81
return true;
110
}
82
}
111
83
112
static void pmevtyper_write(CPUARMState *env, const ARMCPRegInfo *ri,
84
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_narrow_64(DisasContext *s, arg_2reg_shift *a,
113
@@ -XXX,XX +XXX,XX @@ static void pmintenset_write(CPUARMState *env, const ARMCPRegInfo *ri,
85
* This is always a right shift, and the shiftfn is always a
114
/* We have no event counters so only the C bit can be changed */
86
* left-shift helper, which thus needs the negated shift count.
115
value &= pmu_counter_mask(env);
87
*/
116
env->cp15.c9_pminten |= value;
88
- constimm = tcg_const_i64(-a->shift);
117
+ pmu_update_irq(env);
89
+ constimm = tcg_constant_i64(-a->shift);
90
rm1 = tcg_temp_new_i64();
91
rm2 = tcg_temp_new_i64();
92
rd = tcg_temp_new_i32();
93
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_narrow_64(DisasContext *s, arg_2reg_shift *a,
94
tcg_temp_free_i32(rd);
95
tcg_temp_free_i64(rm1);
96
tcg_temp_free_i64(rm2);
97
- tcg_temp_free_i64(constimm);
98
99
return true;
118
}
100
}
119
101
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_narrow_32(DisasContext *s, arg_2reg_shift *a,
120
static void pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
102
/* size == 2 */
121
@@ -XXX,XX +XXX,XX @@ static void pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
103
imm = -a->shift;
122
{
104
}
123
value &= pmu_counter_mask(env);
105
- constimm = tcg_const_i32(imm);
124
env->cp15.c9_pminten &= ~value;
106
+ constimm = tcg_constant_i32(imm);
125
+ pmu_update_irq(env);
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;
126
}
133
}
127
134
128
static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
129
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
130
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmcnten),
131
.writefn = pmcntenclr_write },
132
{ .name = "PMOVSR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 3,
133
- .access = PL0_RW,
134
+ .access = PL0_RW, .type = ARM_CP_IO,
135
.fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmovsr),
136
.accessfn = pmreg_access,
137
.writefn = pmovsr_write,
138
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
139
{ .name = "PMOVSCLR_EL0", .state = ARM_CP_STATE_AA64,
140
.opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 3,
141
.access = PL0_RW, .accessfn = pmreg_access,
142
- .type = ARM_CP_ALIAS,
143
+ .type = ARM_CP_ALIAS | ARM_CP_IO,
144
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
145
.writefn = pmovsr_write,
146
.raw_writefn = raw_write },
147
{ .name = "PMSWINC", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 4,
148
- .access = PL0_W, .accessfn = pmreg_access_swinc, .type = ARM_CP_NO_RAW,
149
+ .access = PL0_W, .accessfn = pmreg_access_swinc,
150
+ .type = ARM_CP_NO_RAW | ARM_CP_IO,
151
.writefn = pmswinc_write },
152
{ .name = "PMSWINC_EL0", .state = ARM_CP_STATE_AA64,
153
.opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 4,
154
- .access = PL0_W, .accessfn = pmreg_access_swinc, .type = ARM_CP_NO_RAW,
155
+ .access = PL0_W, .accessfn = pmreg_access_swinc,
156
+ .type = ARM_CP_NO_RAW | ARM_CP_IO,
157
.writefn = pmswinc_write },
158
{ .name = "PMSELR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 5,
159
.access = PL0_RW, .type = ARM_CP_ALIAS,
160
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmovsset_cp_reginfo[] = {
161
/* PMOVSSET is not implemented in v7 before v7ve */
162
{ .name = "PMOVSSET", .cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 3,
163
.access = PL0_RW, .accessfn = pmreg_access,
164
- .type = ARM_CP_ALIAS,
165
+ .type = ARM_CP_ALIAS | ARM_CP_IO,
166
.fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmovsr),
167
.writefn = pmovsset_write,
168
.raw_writefn = raw_write },
169
{ .name = "PMOVSSET_EL0", .state = ARM_CP_STATE_AA64,
170
.opc0 = 3, .opc1 = 3, .crn = 9, .crm = 14, .opc2 = 3,
171
.access = PL0_RW, .accessfn = pmreg_access,
172
- .type = ARM_CP_ALIAS,
173
+ .type = ARM_CP_ALIAS | ARM_CP_IO,
174
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
175
.writefn = pmovsset_write,
176
.raw_writefn = raw_write },
177
--
135
--
178
2.20.1
136
2.25.1
179
180
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Initialize the keys to a non-zero value on process start.
3
The operation we're performing with the movcond
4
is either min/max depending on cond -- simplify.
5
Use tcg_constant_i64 while we're at it.
4
6
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
10
---
9
linux-user/aarch64/target_syscall.h | 2 ++
11
target/arm/translate-sve.c | 9 ++-------
10
linux-user/aarch64/cpu_loop.c | 31 +++++++++++++++++++++++++++--
12
1 file changed, 2 insertions(+), 7 deletions(-)
11
2 files changed, 31 insertions(+), 2 deletions(-)
12
13
13
diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h
14
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/aarch64/target_syscall.h
16
--- a/target/arm/translate-sve.c
16
+++ b/linux-user/aarch64/target_syscall.h
17
+++ b/target/arm/translate-sve.c
17
@@ -XXX,XX +XXX,XX @@ struct target_pt_regs {
18
@@ -XXX,XX +XXX,XX @@ static bool trans_PNEXT(DisasContext *s, arg_rr_esz *a)
18
#define TARGET_PR_SVE_SET_VL 50
19
static void do_sat_addsub_32(TCGv_i64 reg, TCGv_i64 val, bool u, bool d)
19
#define TARGET_PR_SVE_GET_VL 51
20
{
20
21
int64_t ibound;
21
+void arm_init_pauth_key(ARMPACKey *key);
22
- TCGv_i64 bound;
22
+
23
- TCGCond cond;
23
#endif /* AARCH64_TARGET_SYSCALL_H */
24
24
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
25
/* Use normal 64-bit arithmetic to detect 32-bit overflow. */
25
index XXXXXXX..XXXXXXX 100644
26
if (u) {
26
--- a/linux-user/aarch64/cpu_loop.c
27
@@ -XXX,XX +XXX,XX @@ static void do_sat_addsub_32(TCGv_i64 reg, TCGv_i64 val, bool u, bool d)
27
+++ b/linux-user/aarch64/cpu_loop.c
28
if (d) {
28
@@ -XXX,XX +XXX,XX @@ void cpu_loop(CPUARMState *env)
29
tcg_gen_sub_i64(reg, reg, val);
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));
29
}
38
}
39
- bound = tcg_const_i64(ibound);
40
- tcg_gen_movcond_i64(cond, reg, reg, bound, bound, reg);
41
- tcg_temp_free_i64(bound);
30
}
42
}
31
43
32
+static uint64_t arm_rand64(void)
44
/* Similarly with 64-bit values. */
33
+{
34
+ int shift = 64 - clz64(RAND_MAX);
35
+ int i, n = 64 / shift + (64 % shift != 0);
36
+ uint64_t ret = 0;
37
+
38
+ for (i = 0; i < n; i++) {
39
+ ret = (ret << shift) | rand();
40
+ }
41
+ return ret;
42
+}
43
+
44
+void arm_init_pauth_key(ARMPACKey *key)
45
+{
46
+ key->lo = arm_rand64();
47
+ key->hi = arm_rand64();
48
+}
49
+
50
void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
51
{
52
- CPUState *cpu = ENV_GET_CPU(env);
53
- TaskState *ts = cpu->opaque;
54
+ ARMCPU *cpu = arm_env_get_cpu(env);
55
+ CPUState *cs = CPU(cpu);
56
+ TaskState *ts = cs->opaque;
57
struct image_info *info = ts->info;
58
int i;
59
60
@@ -XXX,XX +XXX,XX @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
61
}
62
#endif
63
64
+ if (cpu_isar_feature(aa64_pauth, cpu)) {
65
+ arm_init_pauth_key(&env->apia_key);
66
+ arm_init_pauth_key(&env->apib_key);
67
+ arm_init_pauth_key(&env->apda_key);
68
+ arm_init_pauth_key(&env->apdb_key);
69
+ arm_init_pauth_key(&env->apga_key);
70
+ }
71
+
72
ts->stack_base = info->start_stack;
73
ts->heap_base = info->brk;
74
/* This will be filled in on the first SYS_HEAPINFO call. */
75
--
45
--
76
2.20.1
46
2.25.1
77
78
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Use tcg_constant_{i32,i64} as appropriate throughout.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
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
--- a/target/arm/translate-vfp.c
15
+++ b/target/arm/translate-vfp.c
16
@@ -XXX,XX +XXX,XX @@ static void gen_update_fp_context(DisasContext *s)
17
gen_helper_vfp_set_fpscr(cpu_env, fpscr);
18
tcg_temp_free_i32(fpscr);
19
if (dc_isar_feature(aa32_mve, s)) {
20
- TCGv_i32 z32 = tcg_const_i32(0);
21
- store_cpu_field(z32, v7m.vpr);
22
+ store_cpu_field(tcg_constant_i32(0), v7m.vpr);
23
}
24
/*
25
* We just updated the FPSCR and VPR. Some of this state is cached
26
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
27
TCGv_i64 frn, frm, dest;
28
TCGv_i64 tmp, zero, zf, nf, vf;
29
30
- zero = tcg_const_i64(0);
31
+ zero = tcg_constant_i64(0);
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;
180
}
181
182
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
183
}
184
}
185
186
- fd = tcg_const_i32(vfp_expand_imm(MO_32, a->imm));
187
+ fd = tcg_constant_i32(vfp_expand_imm(MO_32, a->imm));
188
189
for (;;) {
190
vfp_store_reg32(fd, vd);
191
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
192
vd = vfp_advance_sreg(vd, delta_d);
193
}
194
195
- tcg_temp_free_i32(fd);
196
return true;
197
}
198
199
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
200
}
201
}
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
}
215
216
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a)
217
vfp_load_reg32(vd, a->vd);
218
219
fpst = fpstatus_ptr(FPST_FPCR_F16);
220
- shift = tcg_const_i32(frac_bits);
221
+ shift = tcg_constant_i32(frac_bits);
222
223
/* Switch on op:U:sx bits */
224
switch (a->opc) {
225
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a)
226
227
vfp_store_reg32(vd, a->vd);
228
tcg_temp_free_i32(vd);
229
- tcg_temp_free_i32(shift);
230
tcg_temp_free_ptr(fpst);
231
return true;
232
}
233
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
234
vfp_load_reg32(vd, a->vd);
235
236
fpst = fpstatus_ptr(FPST_FPCR);
237
- shift = tcg_const_i32(frac_bits);
238
+ shift = tcg_constant_i32(frac_bits);
239
240
/* Switch on op:U:sx bits */
241
switch (a->opc) {
242
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
243
244
vfp_store_reg32(vd, a->vd);
245
tcg_temp_free_i32(vd);
246
- tcg_temp_free_i32(shift);
247
tcg_temp_free_ptr(fpst);
248
return true;
249
}
250
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
251
vfp_load_reg64(vd, a->vd);
252
253
fpst = fpstatus_ptr(FPST_FPCR);
254
- shift = tcg_const_i32(frac_bits);
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
--
268
2.25.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
---
6
---
7
linux-user/elfload.c | 1 +
7
target/arm/translate.h | 13 +++----------
8
1 file changed, 1 insertion(+)
8
1 file changed, 3 insertions(+), 10 deletions(-)
9
9
10
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
10
diff --git a/target/arm/translate.h b/target/arm/translate.h
11
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
12
--- a/linux-user/elfload.c
12
--- a/target/arm/translate.h
13
+++ b/linux-user/elfload.c
13
+++ b/target/arm/translate.h
14
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
14
@@ -XXX,XX +XXX,XX @@ static inline void gen_ss_advance(DisasContext *s)
15
GET_FEATURE_ID(aa64_dp, ARM_HWCAP_A64_ASIMDDP);
15
static inline void gen_exception(int excp, uint32_t syndrome,
16
GET_FEATURE_ID(aa64_fcma, ARM_HWCAP_A64_FCMA);
16
uint32_t target_el)
17
GET_FEATURE_ID(aa64_sve, ARM_HWCAP_A64_SVE);
17
{
18
+ GET_FEATURE_ID(aa64_pauth, ARM_HWCAP_A64_PACA | ARM_HWCAP_A64_PACG);
18
- TCGv_i32 tcg_excp = tcg_const_i32(excp);
19
19
- TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
20
#undef GET_FEATURE_ID
20
- TCGv_i32 tcg_el = tcg_const_i32(target_el);
21
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
}
32
33
/* Generate an architectural singlestep exception */
22
--
34
--
23
2.20.1
35
2.25.1
24
25
diff view generated by jsdifflib
1
The PRFM prefetch insn in the load/store with imm9 encodings
1
From: Xiang Chen <chenxiang66@hisilicon.com>
2
requires idx field 0b00; we were underdecoding this by
3
only checking !is_unpriv (which is equivalent to idx != 2).
4
Correctly UNDEF the unallocated encodings where idx == 0b01
5
and 0b11 as well as 0b10.
6
2
7
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
3
It always calls the IOMMU MR translate() callback with flag=IOMMU_NONE in
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
10
Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
11
Reviewed-by: Eric Auger <eric.auger@redhat.com>
12
Message-id: 1650094695-121918-1-git-send-email-chenxiang66@hisilicon.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
10
Message-id: 20190125182626.9221-3-peter.maydell@linaro.org
11
---
14
---
12
target/arm/translate-a64.c | 2 +-
15
hw/arm/smmuv3.c | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
16
1 file changed, 1 insertion(+), 1 deletion(-)
14
17
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
18
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
20
--- a/hw/arm/smmuv3.c
18
+++ b/target/arm/translate-a64.c
21
+++ b/hw/arm/smmuv3.c
19
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
22
@@ -XXX,XX +XXX,XX @@ epilogue:
20
} else {
23
qemu_mutex_unlock(&s->mutex);
21
if (size == 3 && opc == 2) {
24
switch (status) {
22
/* PRFM - prefetch */
25
case SMMU_TRANS_SUCCESS:
23
- if (is_unpriv) {
26
- entry.perm = flag;
24
+ if (idx != 0) {
27
+ entry.perm = cached_entry->entry.perm;
25
unallocated_encoding(s);
28
entry.translated_addr = cached_entry->entry.translated_addr +
26
return;
29
(addr & cached_entry->entry.addr_mask);
27
}
30
entry.addr_mask = cached_entry->entry.addr_mask;
28
--
31
--
29
2.20.1
32
2.25.1
30
31
diff view generated by jsdifflib