1
The following changes since commit 55ef0b702bc2c90c3c4ed97f97676d8f139e5ca1:
1
Arm queue. I still have a lot of stuff in my to-review queue, so
2
won't be long til the next one.
2
3
3
Merge remote-tracking branch 'remotes/lvivier-gitlab/tags/linux-user-for-7.0-pull-request' into staging (2022-02-07 10:48:25 +0000)
4
I've thrown in a couple of minor non-arm patches (a xen code
5
cleanup and a vl.c codestyle issue).
6
7
thanks
8
-- PMM
9
10
The following changes since commit de44c044420d1139480fa50c2d5be19223391218:
11
12
Merge remote-tracking branch 'remotes/stsquad/tags/pull-tcg-testing-revivial-210618-2' into staging (2018-06-22 10:57:47 +0100)
4
13
5
are available in the Git repository at:
14
are available in the Git repository at:
6
15
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220208
16
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180622
8
17
9
for you to fetch changes up to 4fd1ebb10593087d45d2f56f7f3d13447d24802c:
18
for you to fetch changes up to 6dad8260e82b69bd278685ee25209f5824360455:
10
19
11
hw/sensor: Add lsm303dlhc magnetometer device (2022-02-08 10:56:29 +0000)
20
xen: Don't use memory_region_init_ram_nomigrate() in pci_assign_dev_load_option_rom() (2018-06-22 13:28:42 +0100)
12
21
13
----------------------------------------------------------------
22
----------------------------------------------------------------
14
target-arm queue:
23
target-arm queue:
15
* Fix handling of SVE ZCR_LEN when using VHE
24
* hw/intc/arm_gicv3: fix wrong values when reading IPRIORITYR
16
* xlnx-zynqmp: 'Or' the QSPI / QSPI DMA IRQs
25
* target/arm: fix read of freed memory in kvm_arm_machine_init_done()
17
* Don't ever enable PSCI when booting guest in EL3
26
* virt: support up to 512 CPUs
18
* Adhere to SMCCC 1.3 section 5.2
27
* virt: support 256MB ECAM PCI region (for more PCI devices)
19
* highbank: Fix issues with booting SMP
28
* xlnx-zynqmp: Use Cortex-R5F, not Cortex-R5
20
* midway: Fix issues booting at all
29
* mps2-tz: Implement and use the TrustZone Memory Protection Controller
21
* boot: Drop existing dtb /psci node rather than retaining it
30
* target/arm: enforce alignment checking for v6M cores
22
* versal-virt: Always call arm_load_kernel()
31
* xen: Don't use memory_region_init_ram_nomigrate() in pci_assign_dev_load_option_rom()
23
* force flag recalculation when messing with DAIF
32
* vl.c: Don't zero-initialize statics for serial_hds
24
* hw/timer/armv7m_systick: Update clock source before enabling timer
25
* hw/arm/smmuv3: Fix device reset
26
* hw/intc/arm_gicv3_its: refactorings and minor bug fixes
27
* hw/sensor: Add lsm303dlhc magnetometer device
28
33
29
----------------------------------------------------------------
34
----------------------------------------------------------------
30
Alex Bennée (1):
35
Amol Surati (1):
31
arm: force flag recalculation when messing with DAIF
36
hw/intc/arm_gicv3: fix an extra left-shift when reading IPRIORITYR
32
37
33
Edgar E. Iglesias (1):
38
Edgar E. Iglesias (2):
34
hw/arm: versal-virt: Always call arm_load_kernel()
39
target-arm: Add the Cortex-R5F
40
xlnx-zynqmp: Swap Cortex-R5 for Cortex-R5F
35
41
36
Eric Auger (1):
42
Eric Auger (11):
37
hw/arm/smmuv3: Fix device reset
43
linux-headers: Update to kernel mainline commit b357bf602
44
target/arm: Allow KVM device address overwriting
45
hw/intc/arm_gicv3: Introduce redist-region-count array property
46
hw/intc/arm_gicv3_kvm: Get prepared to handle multiple redist regions
47
hw/arm/virt: GICv3 DT node with one or two redistributor regions
48
hw/arm/virt-acpi-build: Advertise one or two GICR structures
49
hw/arm/virt: Register two redistributor regions when necessary
50
hw/arm/virt: Add a new 256MB ECAM region
51
hw/arm/virt: Add virt-3.0 machine type
52
hw/arm/virt: Use 256MB ECAM region by default
53
hw/arm/virt: Increase max_cpus to 512
38
54
39
Francisco Iglesias (1):
55
Julia Suvorova (3):
40
hw/arm/xlnx-zynqmp: 'Or' the QSPI / QSPI DMA IRQs
56
target/arm: Minor cleanup for ARMv6-M 32-bit instructions
57
target/arm: Introduce ARM_FEATURE_M_MAIN
58
target/arm: Strict alignment for ARMv6-M and ARMv8-M Baseline
41
59
42
Kevin Townsend (1):
60
Peter Maydell (10):
43
hw/sensor: Add lsm303dlhc magnetometer device
61
hw/misc/tz-mpc.c: Implement the Arm TrustZone Memory Protection Controller
62
hw/misc/tz-mpc.c: Implement registers
63
hw/misc/tz-mpc.c: Implement correct blocked-access behaviour
64
hw/misc/tz_mpc.c: Honour the BLK_LUT settings in translate
65
hw/misc/iotkit-secctl.c: Implement SECMPCINTSTATUS
66
hw/arm/iotkit: Instantiate MPC
67
hw/arm/iotkit: Wire up MPC interrupt lines
68
hw/arm/mps2-tz.c: Instantiate MPCs
69
vl.c: Don't zero-initialize statics for serial_hds
70
xen: Don't use memory_region_init_ram_nomigrate() in pci_assign_dev_load_option_rom()
44
71
45
Peter Maydell (29):
72
Zheng Xiang (1):
46
target/arm: make psci-conduit settable after realize
73
target-arm: fix a segmentation fault due to illegal memory access
47
cpu.c: Make start-powered-off settable after realize
48
hw/arm/boot: Support setting psci-conduit based on guest EL
49
hw/arm: imx: Don't enable PSCI conduit when booting guest in EL3
50
hw/arm: allwinner: Don't enable PSCI conduit when booting guest in EL3
51
hw/arm/xlnx-zcu102: Don't enable PSCI conduit when booting guest in EL3
52
hw/arm/versal: Let boot.c handle PSCI enablement
53
hw/arm/virt: Let boot.c handle PSCI enablement
54
hw/arm: highbank: For EL3 guests, don't enable PSCI, start all cores
55
arm: tcg: Adhere to SMCCC 1.3 section 5.2
56
hw/arm/highbank: Drop use of secure_board_setup
57
hw/arm/boot: Prevent setting both psci_conduit and secure_board_setup
58
hw/arm/boot: Don't write secondary boot stub if using PSCI
59
hw/arm/highbank: Drop unused secondary boot stub code
60
hw/arm/boot: Drop nb_cpus field from arm_boot_info
61
hw/arm/boot: Drop existing dtb /psci node rather than retaining it
62
hw/intc/arm_gicv3_its: Use address_space_map() to access command queue packets
63
hw/intc/arm_gicv3_its: Keep DTEs as a struct, not a raw uint64_t
64
hw/intc/arm_gicv3_its: Pass DTEntry to update_dte()
65
hw/intc/arm_gicv3_its: Keep CTEs as a struct, not a raw uint64_t
66
hw/intc/arm_gicv3_its: Pass CTEntry to update_cte()
67
hw/intc/arm_gicv3_its: Fix address calculation in get_ite() and update_ite()
68
hw/intc/arm_gicv3_its: Avoid nested ifs in get_ite()
69
hw/intc/arm_gicv3_its: Pass ITE values back from get_ite() via a struct
70
hw/intc/arm_gicv3_its: Make update_ite() use ITEntry
71
hw/intc/arm_gicv3_its: Drop TableDesc and CmdQDesc valid fields
72
hw/intc/arm_gicv3_its: In MAPC with V=0, don't check rdbase field
73
hw/intc/arm_gicv3_its: Don't allow intid 1023 in MAPI/MAPTI
74
hw/intc/arm_gicv3_its: Split error checks
75
74
76
Richard Henderson (4):
75
hw/misc/Makefile.objs | 1 +
77
target/arm: Fix sve_zcr_len_for_el for VHE mode running
76
hw/xen/xen_pt.h | 2 +-
78
target/arm: Tidy sve_exception_el for CPACR_EL1 access
77
include/hw/arm/iotkit.h | 8 +
79
target/arm: Fix {fp, sve}_exception_el for VHE mode running
78
include/hw/arm/virt.h | 19 +
80
target/arm: Use CPTR_TFP with CPTR_EL3 in fp_exception_el
79
include/hw/intc/arm_gicv3_common.h | 8 +-
80
include/hw/misc/iotkit-secctl.h | 8 +
81
include/hw/misc/tz-mpc.h | 80 +++
82
include/standard-headers/linux/pci_regs.h | 8 +
83
include/standard-headers/linux/virtio_gpu.h | 1 +
84
include/standard-headers/linux/virtio_net.h | 3 +
85
linux-headers/asm-arm/kvm.h | 1 +
86
linux-headers/asm-arm/unistd-common.h | 1 +
87
linux-headers/asm-arm64/kvm.h | 1 +
88
linux-headers/asm-generic/unistd.h | 4 +-
89
linux-headers/asm-powerpc/unistd.h | 1 +
90
linux-headers/asm-x86/unistd_32.h | 2 +
91
linux-headers/asm-x86/unistd_64.h | 2 +
92
linux-headers/asm-x86/unistd_x32.h | 2 +
93
linux-headers/linux/kvm.h | 5 +-
94
linux-headers/linux/psp-sev.h | 12 +
95
target/arm/cpu.h | 1 +
96
target/arm/kvm_arm.h | 3 +-
97
hw/arm/iotkit.c | 112 +++-
98
hw/arm/mps2-tz.c | 71 ++-
99
hw/arm/virt-acpi-build.c | 30 +-
100
hw/arm/virt.c | 100 +++-
101
hw/arm/xlnx-zcu102.c | 2 +-
102
hw/arm/xlnx-zynqmp.c | 2 +-
103
hw/intc/arm_gic_kvm.c | 4 +-
104
hw/intc/arm_gicv3.c | 12 +-
105
hw/intc/arm_gicv3_common.c | 38 +-
106
hw/intc/arm_gicv3_dist.c | 3 +-
107
hw/intc/arm_gicv3_its_kvm.c | 2 +-
108
hw/intc/arm_gicv3_kvm.c | 44 +-
109
hw/intc/arm_gicv3_redist.c | 3 +-
110
hw/misc/iotkit-secctl.c | 38 +-
111
hw/misc/tz-mpc.c | 628 +++++++++++++++++++++
112
hw/xen/xen_pt_graphics.c | 2 +-
113
hw/xen/xen_pt_load_rom.c | 6 +-
114
target/arm/cpu.c | 12 +
115
target/arm/kvm.c | 11 +-
116
target/arm/translate.c | 45 +-
117
vl.c | 4 +-
118
MAINTAINERS | 2 +
119
default-configs/arm-softmmu.mak | 1 +
120
hw/misc/trace-events | 8 +
121
.../LICENSES/exceptions/Linux-syscall-note | 2 +-
122
linux-headers/LICENSES/preferred/GPL-2.0 | 6 +
123
48 files changed, 1250 insertions(+), 111 deletions(-)
124
create mode 100644 include/hw/misc/tz-mpc.h
125
create mode 100644 hw/misc/tz-mpc.c
81
126
82
Richard Petri (1):
83
hw/timer/armv7m_systick: Update clock source before enabling timer
84
85
hw/intc/gicv3_internal.h | 23 +-
86
include/hw/arm/boot.h | 14 +-
87
include/hw/arm/xlnx-versal.h | 1 -
88
include/hw/arm/xlnx-zynqmp.h | 2 +
89
include/hw/intc/arm_gicv3_its_common.h | 2 -
90
cpu.c | 22 +-
91
hw/arm/allwinner-h3.c | 9 +-
92
hw/arm/aspeed.c | 1 -
93
hw/arm/boot.c | 107 ++++-
94
hw/arm/exynos4_boards.c | 1 -
95
hw/arm/fsl-imx6ul.c | 2 -
96
hw/arm/fsl-imx7.c | 8 +-
97
hw/arm/highbank.c | 72 +---
98
hw/arm/imx25_pdk.c | 3 +-
99
hw/arm/kzm.c | 1 -
100
hw/arm/mcimx6ul-evk.c | 2 +-
101
hw/arm/mcimx7d-sabre.c | 2 +-
102
hw/arm/npcm7xx.c | 3 -
103
hw/arm/orangepi.c | 5 +-
104
hw/arm/raspi.c | 1 -
105
hw/arm/realview.c | 1 -
106
hw/arm/sabrelite.c | 1 -
107
hw/arm/sbsa-ref.c | 1 -
108
hw/arm/smmuv3.c | 6 +
109
hw/arm/vexpress.c | 1 -
110
hw/arm/virt.c | 13 +-
111
hw/arm/xilinx_zynq.c | 1 -
112
hw/arm/xlnx-versal-virt.c | 17 +-
113
hw/arm/xlnx-versal.c | 5 +-
114
hw/arm/xlnx-zcu102.c | 1 +
115
hw/arm/xlnx-zynqmp.c | 25 +-
116
hw/intc/arm_gicv3_its.c | 696 +++++++++++++++------------------
117
hw/sensor/lsm303dlhc_mag.c | 556 ++++++++++++++++++++++++++
118
hw/timer/armv7m_systick.c | 8 +-
119
target/arm/cpu.c | 6 +-
120
target/arm/helper-a64.c | 2 +
121
target/arm/helper.c | 118 ++++--
122
target/arm/psci.c | 35 +-
123
tests/qtest/lsm303dlhc-mag-test.c | 148 +++++++
124
hw/sensor/Kconfig | 4 +
125
hw/sensor/meson.build | 1 +
126
tests/qtest/meson.build | 1 +
127
42 files changed, 1308 insertions(+), 620 deletions(-)
128
create mode 100644 hw/sensor/lsm303dlhc_mag.c
129
create mode 100644 tests/qtest/lsm303dlhc-mag-test.c
130
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Amol Surati <suratiamol@gmail.com>
2
2
3
The recently introduced debug tests in kvm-unit-tests exposed an error
3
When either GICD_IPRIORITYR or GICR_IPRIORITYR is read as a 32-bit
4
in our handling of singlestep cause by stale hflags. This is caught by
4
register, the post left-shift operator in the for loop causes an
5
--enable-debug-tcg when running the tests.
5
extra shift after the least significant byte has been placed.
6
6
7
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
7
The 32-bit value actually returned is therefore the expected value
8
Reported-by: Andrew Jones <drjones@redhat.com>
8
shifted left by 8 bits.
9
Tested-by: Andrew Jones <drjones@redhat.com>
9
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Amol Surati <suratiamol@gmail.com>
11
Message-id: 20220202122353.457084-1-alex.bennee@linaro.org
11
Message-id: 20180614054857.26248-1-suratiamol@gmail.com
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
---
14
target/arm/helper-a64.c | 2 ++
15
hw/intc/arm_gicv3_dist.c | 3 ++-
15
1 file changed, 2 insertions(+)
16
hw/intc/arm_gicv3_redist.c | 3 ++-
17
2 files changed, 4 insertions(+), 2 deletions(-)
16
18
17
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
19
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-a64.c
21
--- a/hw/intc/arm_gicv3_dist.c
20
+++ b/target/arm/helper-a64.c
22
+++ b/hw/intc/arm_gicv3_dist.c
21
@@ -XXX,XX +XXX,XX @@ void HELPER(msr_i_daifset)(CPUARMState *env, uint32_t imm)
23
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
22
{
24
int i, irq = offset - GICD_IPRIORITYR;
23
daif_check(env, 0x1e, imm, GETPC());
25
uint32_t value = 0;
24
env->daif |= (imm << 6) & PSTATE_DAIF;
26
25
+ arm_rebuild_hflags(env);
27
- for (i = irq + 3; i >= irq; i--, value <<= 8) {
26
}
28
+ for (i = irq + 3; i >= irq; i--) {
27
29
+ value <<= 8;
28
void HELPER(msr_i_daifclear)(CPUARMState *env, uint32_t imm)
30
value |= gicd_read_ipriorityr(s, attrs, i);
29
{
31
}
30
daif_check(env, 0x1f, imm, GETPC());
32
*data = value;
31
env->daif &= ~((imm << 6) & PSTATE_DAIF);
33
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
32
+ arm_rebuild_hflags(env);
34
index XXXXXXX..XXXXXXX 100644
33
}
35
--- a/hw/intc/arm_gicv3_redist.c
34
36
+++ b/hw/intc/arm_gicv3_redist.c
35
/* Convert a softfloat float_relation_ (as returned by
37
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_readl(GICv3CPUState *cs, hwaddr offset,
38
int i, irq = offset - GICR_IPRIORITYR;
39
uint32_t value = 0;
40
41
- for (i = irq + 3; i >= irq; i--, value <<= 8) {
42
+ for (i = irq + 3; i >= irq; i--) {
43
+ value <<= 8;
44
value |= gicr_read_ipriorityr(cs, attrs, i);
45
}
46
*data = value;
36
--
47
--
37
2.25.1
48
2.17.1
38
49
39
50
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Julia Suvorova <jusual@mail.ru>
2
2
3
Always call arm_load_kernel() regardless of kernel_filename being
3
The arrays were made static, "if" was simplified because V7M and V8M
4
set. This is needed because arm_load_kernel() sets up reset for
4
define V6 feature.
5
the CPUs.
6
5
7
Fixes: 6f16da53ff (hw/arm: versal: Add a virtual Xilinx Versal board)
6
Signed-off-by: Julia Suvorova <jusual@mail.ru>
8
Reported-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Message-id: 20180618214604.6777-1-jusual@mail.ru
10
Message-id: 20220130110313.4045351-2-edgar.iglesias@gmail.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
11
---
14
hw/arm/xlnx-versal-virt.c | 11 ++---------
12
target/arm/translate.c | 27 +++++++++++++--------------
15
1 file changed, 2 insertions(+), 9 deletions(-)
13
1 file changed, 13 insertions(+), 14 deletions(-)
16
14
17
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
15
diff --git a/target/arm/translate.c b/target/arm/translate.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/xlnx-versal-virt.c
17
--- a/target/arm/translate.c
20
+++ b/hw/arm/xlnx-versal-virt.c
18
+++ b/target/arm/translate.c
21
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
19
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
22
s->binfo.get_dtb = versal_virt_get_dtb;
20
!arm_dc_feature(s, ARM_FEATURE_V7)) {
23
s->binfo.modify_dtb = versal_virt_modify_dtb;
21
int i;
24
s->binfo.psci_conduit = psci_conduit;
22
bool found = false;
25
- if (machine->kernel_filename) {
23
- const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
26
- arm_load_kernel(&s->soc.fpd.apu.cpu[0], machine, &s->binfo);
24
- 0xf3b08040 /* dsb */,
27
- } else {
25
- 0xf3b08050 /* dmb */,
28
- AddressSpace *as = arm_boot_address_space(&s->soc.fpd.apu.cpu[0],
26
- 0xf3b08060 /* isb */,
29
- &s->binfo);
27
- 0xf3e08000 /* mrs */,
30
+ if (!machine->kernel_filename) {
28
- 0xf000d000 /* bl */};
31
/* Some boot-loaders (e.g u-boot) don't like blobs at address 0 (NULL).
29
- const uint32_t armv6m_mask[] = {0xffe0d000,
32
* Offset things by 4K. */
30
- 0xfff0d0f0,
33
s->binfo.loader_start = 0x1000;
31
- 0xfff0d0f0,
34
s->binfo.dtb_limit = 0x1000000;
32
- 0xfff0d0f0,
35
- if (arm_load_dtb(s->binfo.loader_start,
33
- 0xffe0d000,
36
- &s->binfo, s->binfo.dtb_limit, as, machine) < 0) {
34
- 0xf800d000};
37
- exit(EXIT_FAILURE);
35
+ static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
38
- }
36
+ 0xf3b08040 /* dsb */,
39
}
37
+ 0xf3b08050 /* dmb */,
40
+ arm_load_kernel(&s->soc.fpd.apu.cpu[0], machine, &s->binfo);
38
+ 0xf3b08060 /* isb */,
41
39
+ 0xf3e08000 /* mrs */,
42
for (i = 0; i < XLNX_VERSAL_NUM_OSPI_FLASH; i++) {
40
+ 0xf000d000 /* bl */};
43
BusState *spi_bus;
41
+ static const uint32_t armv6m_mask[] = {0xffe0d000,
42
+ 0xfff0d0f0,
43
+ 0xfff0d0f0,
44
+ 0xfff0d0f0,
45
+ 0xffe0d000,
46
+ 0xf800d000};
47
48
for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
49
if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
50
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
51
break;
52
case 3: /* Special control operations. */
53
if (!arm_dc_feature(s, ARM_FEATURE_V7) &&
54
- !(arm_dc_feature(s, ARM_FEATURE_V6) &&
55
- arm_dc_feature(s, ARM_FEATURE_M))) {
56
+ !arm_dc_feature(s, ARM_FEATURE_M)) {
57
goto illegal_op;
58
}
59
op = (insn >> 4) & 0xf;
44
--
60
--
45
2.25.1
61
2.17.1
46
62
47
63
diff view generated by jsdifflib
1
The SMCCC 1.3 spec section 5.2 says
1
From: Zheng Xiang <xiang.zheng@linaro.org>
2
2
3
The Unknown SMC Function Identifier is a sign-extended value of (-1)
3
The elements of kvm_devices_head list are freed in kvm_arm_machine_init_done(),
4
that is returned in the R0, W0 or X0 registers. An implementation must
4
but we still access these illegal memory in kvm_arm_devlistener_del().
5
return this error code when it receives:
6
5
7
* An SMC or HVC call with an unknown Function Identifier
6
This will cause segment fault when booting guest with MALLOC_PERTURB_=1.
8
* An SMC or HVC call for a removed Function Identifier
9
* An SMC64/HVC64 call from AArch32 state
10
7
11
To comply with these statements, let's always return -1 when we encounter
8
Signed-off-by: Zheng Xiang <xiang.zheng@linaro.org>
12
an unknown HVC or SMC call.
9
Message-id: 20180619075821.9884-1-zhengxiang9@huawei.com
13
14
[PMM:
15
This is a reinstatement of commit 9fcd15b9193e819b, previously
16
reverted in commit 4825eaae4fdd56fba0f; we can do this now that we
17
have arranged for all the affected board models to not enable the
18
PSCI emulation if they are running guest code at EL3. This avoids
19
the regressions that caused us to revert the change for 7.0.]
20
21
Signed-off-by: Alexander Graf <agraf@csgraf.de>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
24
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
25
Tested-by: Cédric Le Goater <clg@kaod.org>
26
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
27
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
---
12
---
30
target/arm/psci.c | 35 ++++++-----------------------------
13
target/arm/kvm.c | 1 +
31
1 file changed, 6 insertions(+), 29 deletions(-)
14
1 file changed, 1 insertion(+)
32
15
33
diff --git a/target/arm/psci.c b/target/arm/psci.c
16
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
34
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/psci.c
18
--- a/target/arm/kvm.c
36
+++ b/target/arm/psci.c
19
+++ b/target/arm/kvm.c
37
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_machine_init_done(Notifier *notifier, void *data)
38
21
kvm_arm_set_device_addr(kd);
39
bool arm_is_psci_call(ARMCPU *cpu, int excp_type)
22
}
40
{
23
memory_region_unref(kd->mr);
41
- /* Return true if the r0/x0 value indicates a PSCI call and
24
+ QSLIST_REMOVE_HEAD(&kvm_devices_head, entries);
42
- * the exception type matches the configured PSCI conduit. This is
25
g_free(kd);
43
- * called before the SMC/HVC instruction is executed, to decide whether
44
- * we should treat it as a PSCI call or with the architecturally
45
+ /*
46
+ * Return true if the exception type matches the configured PSCI conduit.
47
+ * This is called before the SMC/HVC instruction is executed, to decide
48
+ * whether we should treat it as a PSCI call or with the architecturally
49
* defined behaviour for an SMC or HVC (which might be UNDEF or trap
50
* to EL2 or to EL3).
51
*/
52
- CPUARMState *env = &cpu->env;
53
- uint64_t param = is_a64(env) ? env->xregs[0] : env->regs[0];
54
55
switch (excp_type) {
56
case EXCP_HVC:
57
@@ -XXX,XX +XXX,XX @@ bool arm_is_psci_call(ARMCPU *cpu, int excp_type)
58
return false;
59
}
26
}
60
27
memory_listener_unregister(&devlistener);
61
- switch (param) {
62
- case QEMU_PSCI_0_2_FN_PSCI_VERSION:
63
- case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
64
- case QEMU_PSCI_0_2_FN_AFFINITY_INFO:
65
- case QEMU_PSCI_0_2_FN64_AFFINITY_INFO:
66
- case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
67
- case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
68
- case QEMU_PSCI_0_1_FN_CPU_ON:
69
- case QEMU_PSCI_0_2_FN_CPU_ON:
70
- case QEMU_PSCI_0_2_FN64_CPU_ON:
71
- case QEMU_PSCI_0_1_FN_CPU_OFF:
72
- case QEMU_PSCI_0_2_FN_CPU_OFF:
73
- case QEMU_PSCI_0_1_FN_CPU_SUSPEND:
74
- case QEMU_PSCI_0_2_FN_CPU_SUSPEND:
75
- case QEMU_PSCI_0_2_FN64_CPU_SUSPEND:
76
- case QEMU_PSCI_0_1_FN_MIGRATE:
77
- case QEMU_PSCI_0_2_FN_MIGRATE:
78
- return true;
79
- default:
80
- return false;
81
- }
82
+ return true;
83
}
84
85
void arm_handle_psci_call(ARMCPU *cpu)
86
@@ -XXX,XX +XXX,XX @@ void arm_handle_psci_call(ARMCPU *cpu)
87
break;
88
case QEMU_PSCI_0_1_FN_MIGRATE:
89
case QEMU_PSCI_0_2_FN_MIGRATE:
90
+ default:
91
ret = QEMU_PSCI_RET_NOT_SUPPORTED;
92
break;
93
- default:
94
- g_assert_not_reached();
95
}
96
97
err:
98
--
28
--
99
2.25.1
29
2.17.1
100
30
101
31
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
When HCR_EL2.{E2H,TGE} == '11', ZCR_EL1 is unused.
3
Update our kernel headers to mainline commit
4
4
b357bf6023a948cf6a9472f07a1b0caac0e4f8e8
5
Reported-by: Zenghui Yu <yuzenghui@huawei.com>
5
("Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm")
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Eric Auger <eric.auger@redhat.com>
8
Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>
8
Message-id: 1529072910-16156-2-git-send-email-eric.auger@redhat.com
9
Message-id: 20220127063428.30212-2-richard.henderson@linaro.org
9
[PMM: clarified commit message]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
target/arm/helper.c | 3 ++-
12
include/standard-headers/linux/pci_regs.h | 8 ++++++++
13
1 file changed, 2 insertions(+), 1 deletion(-)
13
include/standard-headers/linux/virtio_gpu.h | 1 +
14
14
include/standard-headers/linux/virtio_net.h | 3 +++
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
linux-headers/asm-arm/kvm.h | 1 +
16
index XXXXXXX..XXXXXXX 100644
16
linux-headers/asm-arm/unistd-common.h | 1 +
17
--- a/target/arm/helper.c
17
linux-headers/asm-arm64/kvm.h | 1 +
18
+++ b/target/arm/helper.c
18
linux-headers/asm-generic/unistd.h | 4 +++-
19
@@ -XXX,XX +XXX,XX @@ uint32_t sve_zcr_len_for_el(CPUARMState *env, int el)
19
linux-headers/asm-powerpc/unistd.h | 1 +
20
ARMCPU *cpu = env_archcpu(env);
20
linux-headers/asm-x86/unistd_32.h | 2 ++
21
uint32_t zcr_len = cpu->sve_max_vq - 1;
21
linux-headers/asm-x86/unistd_64.h | 2 ++
22
22
linux-headers/asm-x86/unistd_x32.h | 2 ++
23
- if (el <= 1) {
23
linux-headers/linux/kvm.h | 5 +++--
24
+ if (el <= 1 &&
24
linux-headers/linux/psp-sev.h | 12 ++++++++++++
25
+ (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
25
linux-headers/LICENSES/exceptions/Linux-syscall-note | 2 +-
26
zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[1]);
26
linux-headers/LICENSES/preferred/GPL-2.0 | 6 ++++++
27
}
27
15 files changed, 47 insertions(+), 4 deletions(-)
28
if (el <= 2 && arm_feature(env, ARM_FEATURE_EL2)) {
28
29
diff --git a/include/standard-headers/linux/pci_regs.h b/include/standard-headers/linux/pci_regs.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/include/standard-headers/linux/pci_regs.h
32
+++ b/include/standard-headers/linux/pci_regs.h
33
@@ -XXX,XX +XXX,XX @@
34
#define PCI_EXP_DEVCTL_READRQ_256B 0x1000 /* 256 Bytes */
35
#define PCI_EXP_DEVCTL_READRQ_512B 0x2000 /* 512 Bytes */
36
#define PCI_EXP_DEVCTL_READRQ_1024B 0x3000 /* 1024 Bytes */
37
+#define PCI_EXP_DEVCTL_READRQ_2048B 0x4000 /* 2048 Bytes */
38
+#define PCI_EXP_DEVCTL_READRQ_4096B 0x5000 /* 4096 Bytes */
39
#define PCI_EXP_DEVCTL_BCR_FLR 0x8000 /* Bridge Configuration Retry / FLR */
40
#define PCI_EXP_DEVSTA        10    /* Device Status */
41
#define PCI_EXP_DEVSTA_CED    0x0001    /* Correctable Error Detected */
42
@@ -XXX,XX +XXX,XX @@
43
#define PCI_EXP_LNKCAP2_SLS_16_0GB    0x00000010 /* Supported Speed 16GT/s */
44
#define PCI_EXP_LNKCAP2_CROSSLINK    0x00000100 /* Crosslink supported */
45
#define PCI_EXP_LNKCTL2        48    /* Link Control 2 */
46
+#define PCI_EXP_LNKCTL2_TLS        0x000f
47
+#define PCI_EXP_LNKCTL2_TLS_2_5GT    0x0001 /* Supported Speed 2.5GT/s */
48
+#define PCI_EXP_LNKCTL2_TLS_5_0GT    0x0002 /* Supported Speed 5GT/s */
49
+#define PCI_EXP_LNKCTL2_TLS_8_0GT    0x0003 /* Supported Speed 8GT/s */
50
+#define PCI_EXP_LNKCTL2_TLS_16_0GT    0x0004 /* Supported Speed 16GT/s */
51
#define PCI_EXP_LNKSTA2        50    /* Link Status 2 */
52
#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2    52    /* v2 endpoints with link end here */
53
#define PCI_EXP_SLTCAP2        52    /* Slot Capabilities 2 */
54
@@ -XXX,XX +XXX,XX @@
55
#define PCI_EXP_DPC_CAP_DL_ACTIVE    0x1000    /* ERR_COR signal on DL_Active supported */
56
57
#define PCI_EXP_DPC_CTL            6    /* DPC control */
58
+#define PCI_EXP_DPC_CTL_EN_FATAL     0x0001    /* Enable trigger on ERR_FATAL message */
59
#define PCI_EXP_DPC_CTL_EN_NONFATAL     0x0002    /* Enable trigger on ERR_NONFATAL message */
60
#define PCI_EXP_DPC_CTL_INT_EN     0x0008    /* DPC Interrupt Enable */
61
62
diff --git a/include/standard-headers/linux/virtio_gpu.h b/include/standard-headers/linux/virtio_gpu.h
63
index XXXXXXX..XXXXXXX 100644
64
--- a/include/standard-headers/linux/virtio_gpu.h
65
+++ b/include/standard-headers/linux/virtio_gpu.h
66
@@ -XXX,XX +XXX,XX @@ struct virtio_gpu_cmd_submit {
67
};
68
69
#define VIRTIO_GPU_CAPSET_VIRGL 1
70
+#define VIRTIO_GPU_CAPSET_VIRGL2 2
71
72
/* VIRTIO_GPU_CMD_GET_CAPSET_INFO */
73
struct virtio_gpu_get_capset_info {
74
diff --git a/include/standard-headers/linux/virtio_net.h b/include/standard-headers/linux/virtio_net.h
75
index XXXXXXX..XXXXXXX 100644
76
--- a/include/standard-headers/linux/virtio_net.h
77
+++ b/include/standard-headers/linux/virtio_net.h
78
@@ -XXX,XX +XXX,XX @@
79
                     * Steering */
80
#define VIRTIO_NET_F_CTRL_MAC_ADDR 23    /* Set MAC address */
81
82
+#define VIRTIO_NET_F_STANDBY     62    /* Act as standby for another device
83
+                     * with the same MAC.
84
+                     */
85
#define VIRTIO_NET_F_SPEED_DUPLEX 63    /* Device set linkspeed and duplex */
86
87
#ifndef VIRTIO_NET_NO_LEGACY
88
diff --git a/linux-headers/asm-arm/kvm.h b/linux-headers/asm-arm/kvm.h
89
index XXXXXXX..XXXXXXX 100644
90
--- a/linux-headers/asm-arm/kvm.h
91
+++ b/linux-headers/asm-arm/kvm.h
92
@@ -XXX,XX +XXX,XX @@ struct kvm_regs {
93
#define KVM_VGIC_V3_ADDR_TYPE_DIST    2
94
#define KVM_VGIC_V3_ADDR_TYPE_REDIST    3
95
#define KVM_VGIC_ITS_ADDR_TYPE        4
96
+#define KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION    5
97
98
#define KVM_VGIC_V3_DIST_SIZE        SZ_64K
99
#define KVM_VGIC_V3_REDIST_SIZE        (2 * SZ_64K)
100
diff --git a/linux-headers/asm-arm/unistd-common.h b/linux-headers/asm-arm/unistd-common.h
101
index XXXXXXX..XXXXXXX 100644
102
--- a/linux-headers/asm-arm/unistd-common.h
103
+++ b/linux-headers/asm-arm/unistd-common.h
104
@@ -XXX,XX +XXX,XX @@
105
#define __NR_pkey_alloc (__NR_SYSCALL_BASE + 395)
106
#define __NR_pkey_free (__NR_SYSCALL_BASE + 396)
107
#define __NR_statx (__NR_SYSCALL_BASE + 397)
108
+#define __NR_rseq (__NR_SYSCALL_BASE + 398)
109
110
#endif /* _ASM_ARM_UNISTD_COMMON_H */
111
diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h
112
index XXXXXXX..XXXXXXX 100644
113
--- a/linux-headers/asm-arm64/kvm.h
114
+++ b/linux-headers/asm-arm64/kvm.h
115
@@ -XXX,XX +XXX,XX @@ struct kvm_regs {
116
#define KVM_VGIC_V3_ADDR_TYPE_DIST    2
117
#define KVM_VGIC_V3_ADDR_TYPE_REDIST    3
118
#define KVM_VGIC_ITS_ADDR_TYPE        4
119
+#define KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION    5
120
121
#define KVM_VGIC_V3_DIST_SIZE        SZ_64K
122
#define KVM_VGIC_V3_REDIST_SIZE        (2 * SZ_64K)
123
diff --git a/linux-headers/asm-generic/unistd.h b/linux-headers/asm-generic/unistd.h
124
index XXXXXXX..XXXXXXX 100644
125
--- a/linux-headers/asm-generic/unistd.h
126
+++ b/linux-headers/asm-generic/unistd.h
127
@@ -XXX,XX +XXX,XX @@ __SYSCALL(__NR_pkey_alloc, sys_pkey_alloc)
128
__SYSCALL(__NR_pkey_free, sys_pkey_free)
129
#define __NR_statx 291
130
__SYSCALL(__NR_statx, sys_statx)
131
+#define __NR_io_pgetevents 292
132
+__SC_COMP(__NR_io_pgetevents, sys_io_pgetevents, compat_sys_io_pgetevents)
133
134
#undef __NR_syscalls
135
-#define __NR_syscalls 292
136
+#define __NR_syscalls 293
137
138
/*
139
* 32 bit systems traditionally used different
140
diff --git a/linux-headers/asm-powerpc/unistd.h b/linux-headers/asm-powerpc/unistd.h
141
index XXXXXXX..XXXXXXX 100644
142
--- a/linux-headers/asm-powerpc/unistd.h
143
+++ b/linux-headers/asm-powerpc/unistd.h
144
@@ -XXX,XX +XXX,XX @@
145
#define __NR_pkey_alloc        384
146
#define __NR_pkey_free        385
147
#define __NR_pkey_mprotect    386
148
+#define __NR_rseq        387
149
150
#endif /* _ASM_POWERPC_UNISTD_H_ */
151
diff --git a/linux-headers/asm-x86/unistd_32.h b/linux-headers/asm-x86/unistd_32.h
152
index XXXXXXX..XXXXXXX 100644
153
--- a/linux-headers/asm-x86/unistd_32.h
154
+++ b/linux-headers/asm-x86/unistd_32.h
155
@@ -XXX,XX +XXX,XX @@
156
#define __NR_pkey_free 382
157
#define __NR_statx 383
158
#define __NR_arch_prctl 384
159
+#define __NR_io_pgetevents 385
160
+#define __NR_rseq 386
161
162
#endif /* _ASM_X86_UNISTD_32_H */
163
diff --git a/linux-headers/asm-x86/unistd_64.h b/linux-headers/asm-x86/unistd_64.h
164
index XXXXXXX..XXXXXXX 100644
165
--- a/linux-headers/asm-x86/unistd_64.h
166
+++ b/linux-headers/asm-x86/unistd_64.h
167
@@ -XXX,XX +XXX,XX @@
168
#define __NR_pkey_alloc 330
169
#define __NR_pkey_free 331
170
#define __NR_statx 332
171
+#define __NR_io_pgetevents 333
172
+#define __NR_rseq 334
173
174
#endif /* _ASM_X86_UNISTD_64_H */
175
diff --git a/linux-headers/asm-x86/unistd_x32.h b/linux-headers/asm-x86/unistd_x32.h
176
index XXXXXXX..XXXXXXX 100644
177
--- a/linux-headers/asm-x86/unistd_x32.h
178
+++ b/linux-headers/asm-x86/unistd_x32.h
179
@@ -XXX,XX +XXX,XX @@
180
#define __NR_pkey_alloc (__X32_SYSCALL_BIT + 330)
181
#define __NR_pkey_free (__X32_SYSCALL_BIT + 331)
182
#define __NR_statx (__X32_SYSCALL_BIT + 332)
183
+#define __NR_io_pgetevents (__X32_SYSCALL_BIT + 333)
184
+#define __NR_rseq (__X32_SYSCALL_BIT + 334)
185
#define __NR_rt_sigaction (__X32_SYSCALL_BIT + 512)
186
#define __NR_rt_sigreturn (__X32_SYSCALL_BIT + 513)
187
#define __NR_ioctl (__X32_SYSCALL_BIT + 514)
188
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
189
index XXXXXXX..XXXXXXX 100644
190
--- a/linux-headers/linux/kvm.h
191
+++ b/linux-headers/linux/kvm.h
192
@@ -XXX,XX +XXX,XX @@ struct kvm_ioeventfd {
193
};
194
195
#define KVM_X86_DISABLE_EXITS_MWAIT (1 << 0)
196
-#define KVM_X86_DISABLE_EXITS_HTL (1 << 1)
197
+#define KVM_X86_DISABLE_EXITS_HLT (1 << 1)
198
#define KVM_X86_DISABLE_EXITS_PAUSE (1 << 2)
199
#define KVM_X86_DISABLE_VALID_EXITS (KVM_X86_DISABLE_EXITS_MWAIT | \
200
- KVM_X86_DISABLE_EXITS_HTL | \
201
+ KVM_X86_DISABLE_EXITS_HLT | \
202
KVM_X86_DISABLE_EXITS_PAUSE)
203
204
/* for KVM_ENABLE_CAP */
205
@@ -XXX,XX +XXX,XX @@ struct kvm_ppc_resize_hpt {
206
#define KVM_CAP_S390_BPB 152
207
#define KVM_CAP_GET_MSR_FEATURES 153
208
#define KVM_CAP_HYPERV_EVENTFD 154
209
+#define KVM_CAP_HYPERV_TLBFLUSH 155
210
211
#ifdef KVM_CAP_IRQ_ROUTING
212
213
diff --git a/linux-headers/linux/psp-sev.h b/linux-headers/linux/psp-sev.h
214
index XXXXXXX..XXXXXXX 100644
215
--- a/linux-headers/linux/psp-sev.h
216
+++ b/linux-headers/linux/psp-sev.h
217
@@ -XXX,XX +XXX,XX @@ enum {
218
    SEV_PDH_GEN,
219
    SEV_PDH_CERT_EXPORT,
220
    SEV_PEK_CERT_IMPORT,
221
+    SEV_GET_ID,
222
223
    SEV_MAX,
224
};
225
@@ -XXX,XX +XXX,XX @@ struct sev_user_data_pdh_cert_export {
226
    __u32 cert_chain_len;            /* In/Out */
227
} __attribute__((packed));
228
229
+/**
230
+ * struct sev_user_data_get_id - GET_ID command parameters
231
+ *
232
+ * @socket1: Buffer to pass unique ID of first socket
233
+ * @socket2: Buffer to pass unique ID of second socket
234
+ */
235
+struct sev_user_data_get_id {
236
+    __u8 socket1[64];            /* Out */
237
+    __u8 socket2[64];            /* Out */
238
+} __attribute__((packed));
239
+
240
/**
241
* struct sev_issue_cmd - SEV ioctl parameters
242
*
243
diff --git a/linux-headers/LICENSES/exceptions/Linux-syscall-note b/linux-headers/LICENSES/exceptions/Linux-syscall-note
244
index XXXXXXX..XXXXXXX 100644
245
--- a/linux-headers/LICENSES/exceptions/Linux-syscall-note
246
+++ b/linux-headers/LICENSES/exceptions/Linux-syscall-note
247
@@ -XXX,XX +XXX,XX @@
248
SPDX-Exception-Identifier: Linux-syscall-note
249
SPDX-URL: https://spdx.org/licenses/Linux-syscall-note.html
250
-SPDX-Licenses: GPL-2.0, GPL-2.0+, GPL-1.0+, LGPL-2.0, LGPL-2.0+, LGPL-2.1, LGPL-2.1+
251
+SPDX-Licenses: GPL-2.0, GPL-2.0+, GPL-1.0+, LGPL-2.0, LGPL-2.0+, LGPL-2.1, LGPL-2.1+, GPL-2.0-only, GPL-2.0-or-later
252
Usage-Guide:
253
This exception is used together with one of the above SPDX-Licenses
254
to mark user space API (uapi) header files so they can be included
255
diff --git a/linux-headers/LICENSES/preferred/GPL-2.0 b/linux-headers/LICENSES/preferred/GPL-2.0
256
index XXXXXXX..XXXXXXX 100644
257
--- a/linux-headers/LICENSES/preferred/GPL-2.0
258
+++ b/linux-headers/LICENSES/preferred/GPL-2.0
259
@@ -XXX,XX +XXX,XX @@
260
Valid-License-Identifier: GPL-2.0
261
+Valid-License-Identifier: GPL-2.0-only
262
Valid-License-Identifier: GPL-2.0+
263
+Valid-License-Identifier: GPL-2.0-or-later
264
SPDX-URL: https://spdx.org/licenses/GPL-2.0.html
265
Usage-Guide:
266
To use this license in source code, put one of the following SPDX
267
@@ -XXX,XX +XXX,XX @@ Usage-Guide:
268
guidelines in the licensing rules documentation.
269
For 'GNU General Public License (GPL) version 2 only' use:
270
SPDX-License-Identifier: GPL-2.0
271
+ or
272
+ SPDX-License-Identifier: GPL-2.0-only
273
For 'GNU General Public License (GPL) version 2 or any later version' use:
274
SPDX-License-Identifier: GPL-2.0+
275
+ or
276
+ SPDX-License-Identifier: GPL-2.0-or-later
277
License-Text:
278
279
         GNU GENERAL PUBLIC LICENSE
29
--
280
--
30
2.25.1
281
2.17.1
31
282
32
283
diff view generated by jsdifflib
1
Change the highbank/midway boards to use the new boot.c functionality
1
From: Eric Auger <eric.auger@redhat.com>
2
to allow us to enable psci-conduit only if the guest is being booted
3
in EL1 or EL2, so that if the user runs guest EL3 firmware code our
4
PSCI emulation doesn't get in its way.
5
2
6
To do this we stop setting the psci-conduit and start-powered-off
3
for KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION attribute, the attribute
7
properties on the CPU objects in the board code, and instead set the
4
data pointed to by kvm_device_attr.addr is a OR of the
8
psci_conduit field in the arm_boot_info struct to tell the common
5
redistributor region address and other fields such as the index
9
boot loader code that we'd like PSCI if the guest is starting at an
6
of the redistributor region and the number of redistributors the
10
EL that it makes sense with (in which case it will set these
7
region can contain.
11
properties).
12
8
13
This means that when running guest code at EL3, all the cores
9
The existing machine init done notifier framework sets the address
14
will start execution at once on poweron. This matches the
10
field to the actual address of the device and does not allow to OR
15
real hardware behaviour. (A brief description of the hardware
11
this value with other fields.
16
boot process is in the u-boot documentation for these boards:
17
https://u-boot.readthedocs.io/en/latest/board/highbank/highbank.html#boot-process
18
-- in theory one might run the 'a9boot'/'a15boot' secure monitor
19
code in QEMU, though we probably don't emulate enough for that.)
20
12
21
This affects the highbank and midway boards.
13
This patch extends the KVMDevice struct with a new kda_addr_ormask
14
member. Its value is passed at registration time and OR'ed with the
15
resolved address on kvm_arm_set_device_addr().
22
16
17
Signed-off-by: Eric Auger <eric.auger@redhat.com>
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Message-id: 1529072910-16156-3-git-send-email-eric.auger@redhat.com
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
26
Tested-by: Cédric Le Goater <clg@kaod.org>
27
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
28
Message-id: 20220127154639.2090164-10-peter.maydell@linaro.org
29
---
21
---
30
hw/arm/highbank.c | 7 +------
22
target/arm/kvm_arm.h | 3 ++-
31
1 file changed, 1 insertion(+), 6 deletions(-)
23
hw/intc/arm_gic_kvm.c | 4 ++--
24
hw/intc/arm_gicv3_its_kvm.c | 2 +-
25
hw/intc/arm_gicv3_kvm.c | 4 ++--
26
target/arm/kvm.c | 10 +++++++++-
27
5 files changed, 16 insertions(+), 7 deletions(-)
32
28
33
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
29
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
34
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/highbank.c
31
--- a/target/arm/kvm_arm.h
36
+++ b/hw/arm/highbank.c
32
+++ b/target/arm/kvm_arm.h
37
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
33
@@ -XXX,XX +XXX,XX @@ int kvm_arm_vcpu_init(CPUState *cs);
38
object_property_set_int(cpuobj, "psci-conduit", QEMU_PSCI_CONDUIT_SMC,
34
* @group: device control API group for setting addresses
39
&error_abort);
35
* @attr: device control API address type
40
36
* @dev_fd: device control device file descriptor (or -1 if not supported)
41
- if (n) {
37
+ * @addr_ormask: value to be OR'ed with resolved address
42
- /* Secondary CPUs start in PSCI powered-down state */
38
*
43
- object_property_set_bool(cpuobj, "start-powered-off", true,
39
* Remember the memory region @mr, and when it is mapped by the
44
- &error_abort);
40
* machine model, tell the kernel that base address using the
45
- }
41
@@ -XXX,XX +XXX,XX @@ int kvm_arm_vcpu_init(CPUState *cs);
46
-
42
* address at the point where machine init is complete.
47
if (object_property_find(cpuobj, "reset-cbar")) {
43
*/
48
object_property_set_int(cpuobj, "reset-cbar", MPCORE_PERIPHBASE,
44
void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group,
49
&error_abort);
45
- uint64_t attr, int dev_fd);
50
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
46
+ uint64_t attr, int dev_fd, uint64_t addr_ormask);
51
highbank_binfo.board_setup_addr = BOARD_SETUP_ADDR;
47
52
highbank_binfo.write_board_setup = hb_write_board_setup;
48
/**
53
highbank_binfo.secure_board_setup = true;
49
* kvm_arm_init_cpreg_list:
54
+ highbank_binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
50
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
55
51
index XXXXXXX..XXXXXXX 100644
56
arm_load_kernel(ARM_CPU(first_cpu), machine, &highbank_binfo);
52
--- a/hw/intc/arm_gic_kvm.c
53
+++ b/hw/intc/arm_gic_kvm.c
54
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
55
| KVM_VGIC_V2_ADDR_TYPE_DIST,
56
KVM_DEV_ARM_VGIC_GRP_ADDR,
57
KVM_VGIC_V2_ADDR_TYPE_DIST,
58
- s->dev_fd);
59
+ s->dev_fd, 0);
60
/* CPU interface for current core. Unlike arm_gic, we don't
61
* provide the "interface for core #N" memory regions, because
62
* cores with a VGIC don't have those.
63
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
64
| KVM_VGIC_V2_ADDR_TYPE_CPU,
65
KVM_DEV_ARM_VGIC_GRP_ADDR,
66
KVM_VGIC_V2_ADDR_TYPE_CPU,
67
- s->dev_fd);
68
+ s->dev_fd, 0);
69
70
if (kvm_has_gsi_routing()) {
71
/* set up irq routing */
72
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/hw/intc/arm_gicv3_its_kvm.c
75
+++ b/hw/intc/arm_gicv3_its_kvm.c
76
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
77
78
/* register the base address */
79
kvm_arm_register_device(&s->iomem_its_cntrl, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
80
- KVM_VGIC_ITS_ADDR_TYPE, s->dev_fd);
81
+ KVM_VGIC_ITS_ADDR_TYPE, s->dev_fd, 0);
82
83
gicv3_its_init_mmio(s, NULL);
84
85
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/hw/intc/arm_gicv3_kvm.c
88
+++ b/hw/intc/arm_gicv3_kvm.c
89
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
90
KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true, &error_abort);
91
92
kvm_arm_register_device(&s->iomem_dist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
93
- KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd);
94
+ KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd, 0);
95
kvm_arm_register_device(&s->iomem_redist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
96
- KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd);
97
+ KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd, 0);
98
99
if (kvm_has_gsi_routing()) {
100
/* set up irq routing */
101
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
102
index XXXXXXX..XXXXXXX 100644
103
--- a/target/arm/kvm.c
104
+++ b/target/arm/kvm.c
105
@@ -XXX,XX +XXX,XX @@ unsigned long kvm_arch_vcpu_id(CPUState *cpu)
106
* We use a MemoryListener to track mapping and unmapping of
107
* the regions during board creation, so the board models don't
108
* need to do anything special for the KVM case.
109
+ *
110
+ * Sometimes the address must be OR'ed with some other fields
111
+ * (for example for KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION).
112
+ * @kda_addr_ormask aims at storing the value of those fields.
113
*/
114
typedef struct KVMDevice {
115
struct kvm_arm_device_addr kda;
116
struct kvm_device_attr kdattr;
117
+ uint64_t kda_addr_ormask;
118
MemoryRegion *mr;
119
QSLIST_ENTRY(KVMDevice) entries;
120
int dev_fd;
121
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_set_device_addr(KVMDevice *kd)
122
*/
123
if (kd->dev_fd >= 0) {
124
uint64_t addr = kd->kda.addr;
125
+
126
+ addr |= kd->kda_addr_ormask;
127
attr->addr = (uintptr_t)&addr;
128
ret = kvm_device_ioctl(kd->dev_fd, KVM_SET_DEVICE_ATTR, attr);
129
} else {
130
@@ -XXX,XX +XXX,XX @@ static Notifier notify = {
131
};
132
133
void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group,
134
- uint64_t attr, int dev_fd)
135
+ uint64_t attr, int dev_fd, uint64_t addr_ormask)
136
{
137
KVMDevice *kd;
138
139
@@ -XXX,XX +XXX,XX @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group,
140
kd->kdattr.group = group;
141
kd->kdattr.attr = attr;
142
kd->dev_fd = dev_fd;
143
+ kd->kda_addr_ormask = addr_ormask;
144
QSLIST_INSERT_HEAD(&kvm_devices_head, kd, entries);
145
memory_region_ref(kd->mr);
57
}
146
}
58
--
147
--
59
2.25.1
148
2.17.1
60
149
61
150
diff view generated by jsdifflib
1
Change the iMX-SoC based boards to use the new boot.c functionality
1
From: Eric Auger <eric.auger@redhat.com>
2
to allow us to enable psci-conduit only if the guest is being booted
2
3
in EL1 or EL2, so that if the user runs guest EL3 firmware code our
3
To prepare for multiple redistributor regions, we introduce
4
PSCI emulation doesn't get in its way.
4
an array of uint32_t properties that stores the redistributor
5
5
count of each redistributor region.
6
To do this we stop setting the psci-conduit property on the CPU
6
7
objects in the SoC code, and instead set the psci_conduit field in
7
Non accelerated VGICv3 only supports a single redistributor region.
8
the arm_boot_info struct to tell the common boot loader code that
8
The capacity of all redist regions is checked against the number of
9
we'd like PSCI if the guest is starting at an EL that it makes
9
vcpus.
10
sense with.
10
11
11
Machvirt is updated to set those properties, ie. a single
12
This affects the mcimx6ul-evk and mcimx7d-sabre boards.
12
redistributor region with count set to the number of vcpus
13
13
capped by 123.
14
Note that for the mcimx7d board, this means that when running guest
14
15
code at EL3 there is currently no way to power on the secondary CPUs,
15
Signed-off-by: Eric Auger <eric.auger@redhat.com>
16
because we do not currently have a model of the system reset
16
Reviewed-by: Andrew Jones <drjones@redhat.com>
17
controller module which should be used to do that for the imx7 SoC,
17
Message-id: 1529072910-16156-4-git-send-email-eric.auger@redhat.com
18
only for the imx6 SoC. (Previously EL3 code which knew it was
19
running on QEMU could use a PSCI call to do this.) This doesn't
20
affect the imx6ul-evk board because it is uniprocessor.
21
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
25
Tested-by: Cédric Le Goater <clg@kaod.org>
26
Acked-by: Richard Henderson <richard.henderson@linaro.org>
27
Message-id: 20220127154639.2090164-5-peter.maydell@linaro.org
28
---
19
---
29
hw/arm/fsl-imx6ul.c | 2 --
20
include/hw/intc/arm_gicv3_common.h | 8 +++++--
30
hw/arm/fsl-imx7.c | 8 ++++----
21
hw/arm/virt.c | 11 ++++++++-
31
hw/arm/mcimx6ul-evk.c | 1 +
22
hw/intc/arm_gicv3.c | 12 +++++++++-
32
hw/arm/mcimx7d-sabre.c | 1 +
23
hw/intc/arm_gicv3_common.c | 38 ++++++++++++++++++++++++++----
33
4 files changed, 6 insertions(+), 6 deletions(-)
24
hw/intc/arm_gicv3_kvm.c | 9 +++++--
34
25
5 files changed, 67 insertions(+), 11 deletions(-)
35
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
26
36
index XXXXXXX..XXXXXXX 100644
27
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
37
--- a/hw/arm/fsl-imx6ul.c
28
index XXXXXXX..XXXXXXX 100644
38
+++ b/hw/arm/fsl-imx6ul.c
29
--- a/include/hw/intc/arm_gicv3_common.h
39
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
30
+++ b/include/hw/intc/arm_gicv3_common.h
31
@@ -XXX,XX +XXX,XX @@
32
#define GICV3_MAXIRQ 1020
33
#define GICV3_MAXSPI (GICV3_MAXIRQ - GIC_INTERNAL)
34
35
+#define GICV3_REDIST_SIZE 0x20000
36
+
37
/* Number of SGI target-list bits */
38
#define GICV3_TARGETLIST_BITS 16
39
40
@@ -XXX,XX +XXX,XX @@ struct GICv3State {
41
/*< public >*/
42
43
MemoryRegion iomem_dist; /* Distributor */
44
- MemoryRegion iomem_redist; /* Redistributors */
45
+ MemoryRegion *iomem_redist; /* Redistributor Regions */
46
+ uint32_t *redist_region_count; /* redistributor count within each region */
47
+ uint32_t nb_redist_regions; /* number of redist regions */
48
49
uint32_t num_cpu;
50
uint32_t num_irq;
51
@@ -XXX,XX +XXX,XX @@ typedef struct ARMGICv3CommonClass {
52
} ARMGICv3CommonClass;
53
54
void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
55
- const MemoryRegionOps *ops);
56
+ const MemoryRegionOps *ops, Error **errp);
57
58
#endif
59
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/hw/arm/virt.c
62
+++ b/hw/arm/virt.c
63
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
64
if (!kvm_irqchip_in_kernel()) {
65
qdev_prop_set_bit(gicdev, "has-security-extensions", vms->secure);
66
}
67
+
68
+ if (type == 3) {
69
+ uint32_t redist0_capacity =
70
+ vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
71
+ uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
72
+
73
+ qdev_prop_set_uint32(gicdev, "len-redist-region-count", 1);
74
+ qdev_prop_set_uint32(gicdev, "redist-region-count[0]", redist0_count);
75
+ }
76
qdev_init_nofail(gicdev);
77
gicbusdev = SYS_BUS_DEVICE(gicdev);
78
sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
79
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
80
* many redistributors we can fit into the memory map.
81
*/
82
if (vms->gic_version == 3) {
83
- virt_max_cpus = vms->memmap[VIRT_GIC_REDIST].size / 0x20000;
84
+ virt_max_cpus = vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
85
} else {
86
virt_max_cpus = GIC_NCPU;
87
}
88
diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/hw/intc/arm_gicv3.c
91
+++ b/hw/intc/arm_gicv3.c
92
@@ -XXX,XX +XXX,XX @@ static void arm_gic_realize(DeviceState *dev, Error **errp)
40
return;
93
return;
41
}
94
}
42
95
43
- object_property_set_int(OBJECT(&s->cpu), "psci-conduit",
96
- gicv3_init_irqs_and_mmio(s, gicv3_set_irq, gic_ops);
44
- QEMU_PSCI_CONDUIT_SMC, &error_abort);
97
+ if (s->nb_redist_regions != 1) {
45
qdev_realize(DEVICE(&s->cpu), NULL, &error_abort);
98
+ error_setg(errp, "VGICv3 redist region number(%d) not equal to 1",
46
99
+ s->nb_redist_regions);
47
/*
100
+ return;
48
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
101
+ }
49
index XXXXXXX..XXXXXXX 100644
102
+
50
--- a/hw/arm/fsl-imx7.c
103
+ gicv3_init_irqs_and_mmio(s, gicv3_set_irq, gic_ops, &local_err);
51
+++ b/hw/arm/fsl-imx7.c
104
+ if (local_err) {
52
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
105
+ error_propagate(errp, local_err);
53
for (i = 0; i < smp_cpus; i++) {
106
+ return;
54
o = OBJECT(&s->cpu[i]);
107
+ }
55
108
56
- object_property_set_int(o, "psci-conduit", QEMU_PSCI_CONDUIT_SMC,
109
gicv3_init_cpuif(s);
57
- &error_abort);
110
}
111
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/hw/intc/arm_gicv3_common.c
114
+++ b/hw/intc/arm_gicv3_common.c
115
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_gicv3 = {
116
};
117
118
void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
119
- const MemoryRegionOps *ops)
120
+ const MemoryRegionOps *ops, Error **errp)
121
{
122
SysBusDevice *sbd = SYS_BUS_DEVICE(s);
123
+ int rdist_capacity = 0;
124
int i;
125
126
+ for (i = 0; i < s->nb_redist_regions; i++) {
127
+ rdist_capacity += s->redist_region_count[i];
128
+ }
129
+ if (rdist_capacity < s->num_cpu) {
130
+ error_setg(errp, "Capacity of the redist regions(%d) "
131
+ "is less than number of vcpus(%d)",
132
+ rdist_capacity, s->num_cpu);
133
+ return;
134
+ }
135
+
136
/* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
137
* GPIO array layout is thus:
138
* [0..N-1] spi
139
@@ -XXX,XX +XXX,XX @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
140
141
memory_region_init_io(&s->iomem_dist, OBJECT(s), ops, s,
142
"gicv3_dist", 0x10000);
143
- memory_region_init_io(&s->iomem_redist, OBJECT(s), ops ? &ops[1] : NULL, s,
144
- "gicv3_redist", 0x20000 * s->num_cpu);
58
-
145
-
59
/* On uniprocessor, the CBAR is set to 0 */
146
sysbus_init_mmio(sbd, &s->iomem_dist);
60
if (smp_cpus > 1) {
147
- sysbus_init_mmio(sbd, &s->iomem_redist);
61
object_property_set_int(o, "reset-cbar", FSL_IMX7_A7MPCORE_ADDR,
148
+
62
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
149
+ s->iomem_redist = g_new0(MemoryRegion, s->nb_redist_regions);
63
}
150
+ for (i = 0; i < s->nb_redist_regions; i++) {
64
151
+ char *name = g_strdup_printf("gicv3_redist_region[%d]", i);
65
if (i) {
152
+
66
- /* Secondary CPUs start in PSCI powered-down state */
153
+ memory_region_init_io(&s->iomem_redist[i], OBJECT(s),
67
+ /*
154
+ ops ? &ops[1] : NULL, s, name,
68
+ * Secondary CPUs start in powered-down state (and can be
155
+ s->redist_region_count[i] * GICV3_REDIST_SIZE);
69
+ * powered up via the SRC system reset controller)
156
+ sysbus_init_mmio(sbd, &s->iomem_redist[i]);
70
+ */
157
+ g_free(name);
71
object_property_set_bool(o, "start-powered-off", true,
158
+ }
72
&error_abort);
159
}
73
}
160
74
diff --git a/hw/arm/mcimx6ul-evk.c b/hw/arm/mcimx6ul-evk.c
161
static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
75
index XXXXXXX..XXXXXXX 100644
162
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
76
--- a/hw/arm/mcimx6ul-evk.c
163
}
77
+++ b/hw/arm/mcimx6ul-evk.c
164
}
78
@@ -XXX,XX +XXX,XX @@ static void mcimx6ul_evk_init(MachineState *machine)
165
79
.board_id = -1,
166
+static void arm_gicv3_finalize(Object *obj)
80
.ram_size = machine->ram_size,
167
+{
81
.nb_cpus = machine->smp.cpus,
168
+ GICv3State *s = ARM_GICV3_COMMON(obj);
82
+ .psci_conduit = QEMU_PSCI_CONDUIT_SMC,
169
+
83
};
170
+ g_free(s->redist_region_count);
84
171
+}
85
s = FSL_IMX6UL(object_new(TYPE_FSL_IMX6UL));
172
+
86
diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c
173
static void arm_gicv3_common_reset(DeviceState *dev)
87
index XXXXXXX..XXXXXXX 100644
174
{
88
--- a/hw/arm/mcimx7d-sabre.c
175
GICv3State *s = ARM_GICV3_COMMON(dev);
89
+++ b/hw/arm/mcimx7d-sabre.c
176
@@ -XXX,XX +XXX,XX @@ static Property arm_gicv3_common_properties[] = {
90
@@ -XXX,XX +XXX,XX @@ static void mcimx7d_sabre_init(MachineState *machine)
177
DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32),
91
.board_id = -1,
178
DEFINE_PROP_UINT32("revision", GICv3State, revision, 3),
92
.ram_size = machine->ram_size,
179
DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0),
93
.nb_cpus = machine->smp.cpus,
180
+ DEFINE_PROP_ARRAY("redist-region-count", GICv3State, nb_redist_regions,
94
+ .psci_conduit = QEMU_PSCI_CONDUIT_SMC,
181
+ redist_region_count, qdev_prop_uint32, uint32_t),
95
};
182
DEFINE_PROP_END_OF_LIST(),
96
183
};
97
s = FSL_IMX7(object_new(TYPE_FSL_IMX7));
184
185
@@ -XXX,XX +XXX,XX @@ static const TypeInfo arm_gicv3_common_type = {
186
.instance_size = sizeof(GICv3State),
187
.class_size = sizeof(ARMGICv3CommonClass),
188
.class_init = arm_gicv3_common_class_init,
189
+ .instance_finalize = arm_gicv3_finalize,
190
.abstract = true,
191
.interfaces = (InterfaceInfo []) {
192
{ TYPE_ARM_LINUX_BOOT_IF },
193
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
194
index XXXXXXX..XXXXXXX 100644
195
--- a/hw/intc/arm_gicv3_kvm.c
196
+++ b/hw/intc/arm_gicv3_kvm.c
197
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
198
return;
199
}
200
201
- gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL);
202
+ gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL, &local_err);
203
+ if (local_err) {
204
+ error_propagate(errp, local_err);
205
+ return;
206
+ }
207
208
for (i = 0; i < s->num_cpu; i++) {
209
ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i));
210
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
211
212
kvm_arm_register_device(&s->iomem_dist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
213
KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd, 0);
214
- kvm_arm_register_device(&s->iomem_redist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
215
+ kvm_arm_register_device(&s->iomem_redist[0], -1,
216
+ KVM_DEV_ARM_VGIC_GRP_ADDR,
217
KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd, 0);
218
219
if (kvm_has_gsi_routing()) {
98
--
220
--
99
2.25.1
221
2.17.1
100
222
101
223
diff view generated by jsdifflib
1
Currently we expect board code to set the psci-conduit property on
1
From: Eric Auger <eric.auger@redhat.com>
2
CPUs and ensure that secondary CPUs are created with the
3
start-powered-off property set to false, if the board wishes to use
4
QEMU's builtin PSCI emulation. This worked OK for the virt board
5
where we first wanted to use it, because the virt board directly
6
creates its CPUs and is in a reasonable position to set those
7
properties. For other boards which model real hardware and use a
8
separate SoC object, however, it is more awkward. Most PSCI-using
9
boards just set the psci-conduit board unconditionally.
10
2
11
This was never strictly speaking correct (because you would not be
3
Let's check if KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION is supported.
12
able to run EL3 guest firmware that itself provided the PSCI
4
If not, we check the number of redist region is equal to 1 and use the
13
interface, as the QEMU implementation would overrule it), but mostly
5
legacy KVM_VGIC_V3_ADDR_TYPE_REDIST attribute. Otherwise we use
14
worked in practice because for non-PSCI SMC calls QEMU would emulate
6
the new attribute and allow to register multiple regions to the
15
the SMC instruction as normal (by trapping to guest EL3). However,
7
KVM device.
16
we would like to make our PSCI emulation follow the part of the SMCC
17
specification that mandates that SMC calls with unknown function
18
identifiers return a failure code, which means that all SMC calls
19
will be handled by the PSCI code and the "emulate as normal" path
20
will no longer be taken.
21
8
22
We tried to implement that in commit 9fcd15b9193e81
9
Signed-off-by: Eric Auger <eric.auger@redhat.com>
23
("arm: tcg: Adhere to SMCCC 1.3 section 5.2"), but this
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
regressed attempts to run EL3 guest code on the affected boards:
11
Reviewed-by: Andrew Jones <drjones@redhat.com>
25
* mcimx6ul-evk, mcimx7d-sabre, orangepi, xlnx-zcu102
12
Message-id: 1529072910-16156-5-git-send-email-eric.auger@redhat.com
26
* for the case only of EL3 code loaded via -kernel (and
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
not via -bios or -pflash), virt and xlnx-versal-virt
14
---
28
so for the 7.0 release we reverted it (in commit 4825eaae4fdd56f).
15
hw/intc/arm_gicv3_kvm.c | 37 ++++++++++++++++++++++++++++++++++---
16
1 file changed, 34 insertions(+), 3 deletions(-)
29
17
30
This commit provides a mechanism that boards can use to arrange that
18
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
31
psci-conduit is set if running guest code at a low enough EL but not
32
if it would be running at the same EL that the conduit implies that
33
the QEMU PSCI implementation is using. (Later commits will convert
34
individual board models to use this mechanism.)
35
36
We do this by moving the setting of the psci-conduit and
37
start-powered-off properties to arm_load_kernel(). Boards which want
38
to potentially use emulated PSCI must set a psci_conduit field in the
39
arm_boot_info struct to the type of conduit they want to use (SMC or
40
HVC); arm_load_kernel() will then set the CPUs up accordingly if it
41
is not going to start the guest code at the same or higher EL as the
42
fake QEMU firmware would be at.
43
44
Board/SoC code which uses this mechanism should no longer set the CPU
45
psci-conduit property directly. It should only set the
46
start-powered-off property for secondaries if EL3 guest firmware
47
running bare metal expects that rather than the alternative "all CPUs
48
start executing the firmware at once".
49
50
Note that when calculating whether we are going to run guest
51
code at EL3, we ignore the setting of arm_boot_info::secure_board_setup,
52
which might cause us to run a stub bit of guest code at EL3 which
53
does some board-specific setup before dropping to EL2 or EL1 to
54
run the guest kernel. This is OK because only one board that
55
enables PSCI sets secure_board_setup (the highbank board), and
56
the stub code it writes will behave the same way whether the
57
one SMC call it makes is handled by "emulate the SMC" or by
58
"PSCI default returns an error code". So we can leave that stub
59
code in place until after we've changed the PSCI default behaviour;
60
at that point we will remove it.
61
62
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
63
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
64
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
65
Tested-by: Cédric Le Goater <clg@kaod.org>
66
Message-id: 20220127154639.2090164-4-peter.maydell@linaro.org
67
---
68
include/hw/arm/boot.h | 10 +++++++++
69
hw/arm/boot.c | 50 +++++++++++++++++++++++++++++++++++++++++++
70
2 files changed, 60 insertions(+)
71
72
diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h
73
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
74
--- a/include/hw/arm/boot.h
20
--- a/hw/intc/arm_gicv3_kvm.c
75
+++ b/include/hw/arm/boot.h
21
+++ b/hw/intc/arm_gicv3_kvm.c
76
@@ -XXX,XX +XXX,XX @@ struct arm_boot_info {
22
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
77
* the user it should implement this hook.
78
*/
79
void (*modify_dtb)(const struct arm_boot_info *info, void *fdt);
80
+ /*
81
+ * If a board wants to use the QEMU emulated-firmware PSCI support,
82
+ * it should set this to QEMU_PSCI_CONDUIT_HVC or QEMU_PSCI_CONDUIT_SMC
83
+ * as appropriate. arm_load_kernel() will set the psci-conduit and
84
+ * start-powered-off properties on the CPUs accordingly.
85
+ * Note that if the guest image is started at the same exception level
86
+ * as the conduit specifies calls should go to (eg guest firmware booted
87
+ * to EL3) then PSCI will not be enabled.
88
+ */
89
+ int psci_conduit;
90
/* Used internally by arm_boot.c */
91
int is_linux;
92
hwaddr initrd_start;
93
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/hw/arm/boot.c
96
+++ b/hw/arm/boot.c
97
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
98
{
23
{
99
CPUState *cs;
24
GICv3State *s = KVM_ARM_GICV3(dev);
100
AddressSpace *as = arm_boot_address_space(cpu, info);
25
KVMARMGICv3Class *kgc = KVM_ARM_GICV3_GET_CLASS(s);
101
+ int boot_el;
26
+ bool multiple_redist_region_allowed;
102
+ CPUARMState *env = &cpu->env;
27
Error *local_err = NULL;
103
28
int i;
104
/*
29
105
* CPU objects (unlike devices) are not automatically reset on system
30
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
106
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
31
return;
107
arm_setup_direct_kernel_boot(cpu, info);
108
}
32
}
109
33
110
+ /*
34
+ multiple_redist_region_allowed =
111
+ * Disable the PSCI conduit if it is set up to target the same
35
+ kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
112
+ * or a lower EL than the one we're going to start the guest code in.
36
+ KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION);
113
+ * This logic needs to agree with the code in do_cpu_reset() which
114
+ * decides whether we're going to boot the guest in the highest
115
+ * supported exception level or in a lower one.
116
+ */
117
+
37
+
118
+ /* Boot into highest supported EL ... */
38
+ if (!multiple_redist_region_allowed && s->nb_redist_regions > 1) {
119
+ if (arm_feature(env, ARM_FEATURE_EL3)) {
39
+ error_setg(errp, "Multiple VGICv3 redistributor regions are not "
120
+ boot_el = 3;
40
+ "supported by this host kernel");
121
+ } else if (arm_feature(env, ARM_FEATURE_EL2)) {
41
+ error_append_hint(errp, "A maximum of %d VCPUs can be used",
122
+ boot_el = 2;
42
+ s->redist_region_count[0]);
123
+ } else {
43
+ return;
124
+ boot_el = 1;
125
+ }
126
+ /* ...except that if we're booting Linux we adjust the EL we boot into */
127
+ if (info->is_linux && !info->secure_boot) {
128
+ boot_el = arm_feature(env, ARM_FEATURE_EL2) ? 2 : 1;
129
+ }
44
+ }
130
+
45
+
131
+ if ((info->psci_conduit == QEMU_PSCI_CONDUIT_HVC && boot_el >= 2) ||
46
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
132
+ (info->psci_conduit == QEMU_PSCI_CONDUIT_SMC && boot_el == 3)) {
47
0, &s->num_irq, true, &error_abort);
133
+ info->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
48
134
+ }
49
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
50
51
kvm_arm_register_device(&s->iomem_dist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
52
KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd, 0);
53
- kvm_arm_register_device(&s->iomem_redist[0], -1,
54
- KVM_DEV_ARM_VGIC_GRP_ADDR,
55
- KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd, 0);
135
+
56
+
136
+ if (info->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
57
+ if (!multiple_redist_region_allowed) {
137
+ for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
58
+ kvm_arm_register_device(&s->iomem_redist[0], -1,
138
+ Object *cpuobj = OBJECT(cs);
59
+ KVM_DEV_ARM_VGIC_GRP_ADDR,
60
+ KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd, 0);
61
+ } else {
62
+ /* we register regions in reverse order as "devices" are inserted at
63
+ * the head of a QSLIST and the list is then popped from the head
64
+ * onwards by kvm_arm_machine_init_done()
65
+ */
66
+ for (i = s->nb_redist_regions - 1; i >= 0; i--) {
67
+ /* Address mask made of the rdist region index and count */
68
+ uint64_t addr_ormask =
69
+ i | ((uint64_t)s->redist_region_count[i] << 52);
139
+
70
+
140
+ object_property_set_int(cpuobj, "psci-conduit", info->psci_conduit,
71
+ kvm_arm_register_device(&s->iomem_redist[i], -1,
141
+ &error_abort);
72
+ KVM_DEV_ARM_VGIC_GRP_ADDR,
142
+ /*
73
+ KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION,
143
+ * Secondary CPUs start in PSCI powered-down state. Like the
74
+ s->dev_fd, addr_ormask);
144
+ * code in do_cpu_reset(), we assume first_cpu is the primary
145
+ * CPU.
146
+ */
147
+ if (cs != first_cpu) {
148
+ object_property_set_bool(cpuobj, "start-powered-off", true,
149
+ &error_abort);
150
+ }
151
+ }
75
+ }
152
+ }
76
+ }
153
+
77
154
+ /*
78
if (kvm_has_gsi_routing()) {
155
+ * arm_load_dtb() may add a PSCI node so it must be called after we have
79
/* set up irq routing */
156
+ * decided whether to enable PSCI and set the psci-conduit CPU properties.
157
+ */
158
if (!info->skip_dtb_autoload && have_dtb(info)) {
159
if (arm_load_dtb(info->dtb_start, info, info->dtb_limit, as, ms) < 0) {
160
exit(1);
161
--
80
--
162
2.25.1
81
2.17.1
163
82
164
83
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
Extract entire fields for ZEN and FPEN, rather than testing specific bits.
3
This patch allows the creation of a GICv3 node with 1 or 2
4
This makes it easier to follow the code versus the ARM spec.
4
redistributor regions depending on the number of smu_cpus.
5
The second redistributor region is located just after the
6
existing RAM region, at 256GB and contains up to up to 512 vcpus.
5
7
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Please refer to kernel documentation for further node details:
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
8
Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>
10
9
Message-id: 20220127063428.30212-3-richard.henderson@linaro.org
11
Signed-off-by: Eric Auger <eric.auger@redhat.com>
12
Reviewed-by: Andrew Jones <drjones@redhat.com>
13
Message-id: 1529072910-16156-6-git-send-email-eric.auger@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
15
---
12
target/arm/helper.c | 36 +++++++++++++++++-------------------
16
include/hw/arm/virt.h | 14 ++++++++++++++
13
1 file changed, 17 insertions(+), 19 deletions(-)
17
hw/arm/virt.c | 29 ++++++++++++++++++++++++-----
18
2 files changed, 38 insertions(+), 5 deletions(-)
14
19
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
16
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
22
--- a/include/hw/arm/virt.h
18
+++ b/target/arm/helper.c
23
+++ b/include/hw/arm/virt.h
19
@@ -XXX,XX +XXX,XX @@ int sve_exception_el(CPUARMState *env, int el)
24
@@ -XXX,XX +XXX,XX @@
20
uint64_t hcr_el2 = arm_hcr_el2_eff(env);
25
#include "qemu/notify.h"
21
26
#include "hw/boards.h"
22
if (el <= 1 && (hcr_el2 & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
27
#include "hw/arm/arm.h"
23
- bool disabled = false;
28
+#include "sysemu/kvm.h"
24
-
29
+#include "hw/intc/arm_gicv3_common.h"
25
- /* The CPACR.ZEN controls traps to EL1:
30
26
- * 0, 2 : trap EL0 and EL1 accesses
31
#define NUM_GICV2M_SPIS 64
27
- * 1 : trap only EL0 accesses
32
#define NUM_VIRTIO_TRANSPORTS 32
28
- * 3 : trap no accesses
33
@@ -XXX,XX +XXX,XX @@ enum {
29
- */
34
VIRT_GIC_V2M,
30
- if (!extract32(env->cp15.cpacr_el1, 16, 1)) {
35
VIRT_GIC_ITS,
31
- disabled = true;
36
VIRT_GIC_REDIST,
32
- } else if (!extract32(env->cp15.cpacr_el1, 17, 1)) {
37
+ VIRT_GIC_REDIST2,
33
- disabled = el == 0;
38
VIRT_SMMU,
34
- }
39
VIRT_UART,
35
- if (disabled) {
40
VIRT_MMIO,
36
+ /* Check CPACR.ZEN. */
41
@@ -XXX,XX +XXX,XX @@ typedef struct {
37
+ switch (extract32(env->cp15.cpacr_el1, 16, 2)) {
42
38
+ case 1:
43
void virt_acpi_setup(VirtMachineState *vms);
39
+ if (el != 0) {
44
40
+ break;
45
+/* Return the number of used redistributor regions */
41
+ }
46
+static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
42
+ /* fall through */
47
+{
43
+ case 0:
48
+ uint32_t redist0_capacity =
44
+ case 2:
49
+ vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
45
/* route_to_el2 */
50
+
46
return hcr_el2 & HCR_TGE ? 2 : 1;
51
+ assert(vms->gic_version == 3);
47
}
52
+
48
53
+ return vms->smp_cpus > redist0_capacity ? 2 : 1;
49
/* Check CPACR.FPEN. */
54
+}
50
- if (!extract32(env->cp15.cpacr_el1, 20, 1)) {
55
+
51
- disabled = true;
56
#endif /* QEMU_ARM_VIRT_H */
52
- } else if (!extract32(env->cp15.cpacr_el1, 21, 1)) {
57
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
53
- disabled = el == 0;
58
index XXXXXXX..XXXXXXX 100644
54
- }
59
--- a/hw/arm/virt.c
55
- if (disabled) {
60
+++ b/hw/arm/virt.c
56
+ switch (extract32(env->cp15.cpacr_el1, 20, 2)) {
61
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry a15memmap[] = {
57
+ case 1:
62
[VIRT_PCIE_PIO] = { 0x3eff0000, 0x00010000 },
58
+ if (el != 0) {
63
[VIRT_PCIE_ECAM] = { 0x3f000000, 0x01000000 },
59
+ break;
64
[VIRT_MEM] = { 0x40000000, RAMLIMIT_BYTES },
60
+ }
65
+ /* Additional 64 MB redist region (can contain up to 512 redistributors) */
61
+ /* fall through */
66
+ [VIRT_GIC_REDIST2] = { 0x4000000000ULL, 0x4000000 },
62
+ case 0:
67
/* Second PCIe window, 512GB wide at the 512GB boundary */
63
+ case 2:
68
[VIRT_PCIE_MMIO_HIGH] = { 0x8000000000ULL, 0x8000000000ULL },
64
return 0;
69
};
65
}
70
@@ -XXX,XX +XXX,XX @@ static void fdt_add_gic_node(VirtMachineState *vms)
66
}
71
qemu_fdt_setprop_cell(vms->fdt, "/intc", "#size-cells", 0x2);
72
qemu_fdt_setprop(vms->fdt, "/intc", "ranges", NULL, 0);
73
if (vms->gic_version == 3) {
74
+ int nb_redist_regions = virt_gicv3_redist_region_count(vms);
75
+
76
qemu_fdt_setprop_string(vms->fdt, "/intc", "compatible",
77
"arm,gic-v3");
78
- qemu_fdt_setprop_sized_cells(vms->fdt, "/intc", "reg",
79
- 2, vms->memmap[VIRT_GIC_DIST].base,
80
- 2, vms->memmap[VIRT_GIC_DIST].size,
81
- 2, vms->memmap[VIRT_GIC_REDIST].base,
82
- 2, vms->memmap[VIRT_GIC_REDIST].size);
83
+
84
+ qemu_fdt_setprop_cell(vms->fdt, "/intc",
85
+ "#redistributor-regions", nb_redist_regions);
86
+
87
+ if (nb_redist_regions == 1) {
88
+ qemu_fdt_setprop_sized_cells(vms->fdt, "/intc", "reg",
89
+ 2, vms->memmap[VIRT_GIC_DIST].base,
90
+ 2, vms->memmap[VIRT_GIC_DIST].size,
91
+ 2, vms->memmap[VIRT_GIC_REDIST].base,
92
+ 2, vms->memmap[VIRT_GIC_REDIST].size);
93
+ } else {
94
+ qemu_fdt_setprop_sized_cells(vms->fdt, "/intc", "reg",
95
+ 2, vms->memmap[VIRT_GIC_DIST].base,
96
+ 2, vms->memmap[VIRT_GIC_DIST].size,
97
+ 2, vms->memmap[VIRT_GIC_REDIST].base,
98
+ 2, vms->memmap[VIRT_GIC_REDIST].size,
99
+ 2, vms->memmap[VIRT_GIC_REDIST2].base,
100
+ 2, vms->memmap[VIRT_GIC_REDIST2].size);
101
+ }
102
+
103
if (vms->virt) {
104
qemu_fdt_setprop_cells(vms->fdt, "/intc", "interrupts",
105
GIC_FDT_IRQ_TYPE_PPI, ARCH_GICV3_MAINT_IRQ,
67
--
106
--
68
2.25.1
107
2.17.1
69
108
70
109
diff view generated by jsdifflib
1
From: Richard Petri <git@rpls.de>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
Starting the SysTick timer and changing the clock source a the same time
3
Depending on the number of smp_cpus we now register one or two
4
will result in an error, if the previous clock period was zero. For exmaple,
4
GICR structures.
5
on the mps2-tz platforms, no refclk is present. Right after reset, the
6
configured ptimer period is zero, and trying to enabling it will turn it off
7
right away. E.g., code running on the platform setting
8
5
9
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
10
7
Reviewed-by: Andrew Jones <drjones@redhat.com>
11
should change the clock source and enable the timer on real hardware, but
8
Message-id: 1529072910-16156-7-git-send-email-eric.auger@redhat.com
12
resulted in an error in qemu.
13
14
Signed-off-by: Richard Petri <git@rpls.de>
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Message-id: 20220201192650.289584-1-git@rpls.de
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
10
---
19
hw/timer/armv7m_systick.c | 8 ++++----
11
hw/arm/virt-acpi-build.c | 9 +++++++++
20
1 file changed, 4 insertions(+), 4 deletions(-)
12
1 file changed, 9 insertions(+)
21
13
22
diff --git a/hw/timer/armv7m_systick.c b/hw/timer/armv7m_systick.c
14
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
23
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/timer/armv7m_systick.c
16
--- a/hw/arm/virt-acpi-build.c
25
+++ b/hw/timer/armv7m_systick.c
17
+++ b/hw/arm/virt-acpi-build.c
26
@@ -XXX,XX +XXX,XX @@ static MemTxResult systick_write(void *opaque, hwaddr addr,
18
@@ -XXX,XX +XXX,XX @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
27
s->control &= 0xfffffff8;
19
28
s->control |= value & 7;
20
if (vms->gic_version == 3) {
29
21
AcpiMadtGenericTranslator *gic_its;
30
+ if ((oldval ^ value) & SYSTICK_CLKSOURCE) {
22
+ int nb_redist_regions = virt_gicv3_redist_region_count(vms);
31
+ systick_set_period_from_clock(s);
23
AcpiMadtGenericRedistributor *gicr = acpi_data_push(table_data,
24
sizeof *gicr);
25
26
@@ -XXX,XX +XXX,XX @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
27
gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST].base);
28
gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST].size);
29
30
+ if (nb_redist_regions == 2) {
31
+ gicr = acpi_data_push(table_data, sizeof(*gicr));
32
+ gicr->type = ACPI_APIC_GENERIC_REDISTRIBUTOR;
33
+ gicr->length = sizeof(*gicr);
34
+ gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST2].base);
35
+ gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST2].size);
32
+ }
36
+ }
33
+
37
+
34
if ((oldval ^ value) & SYSTICK_ENABLE) {
38
if (its_class_name() && !vmc->no_its) {
35
if (value & SYSTICK_ENABLE) {
39
gic_its = acpi_data_push(table_data, sizeof *gic_its);
36
ptimer_run(s->ptimer, 0);
40
gic_its->type = ACPI_APIC_GENERIC_TRANSLATOR;
37
@@ -XXX,XX +XXX,XX @@ static MemTxResult systick_write(void *opaque, hwaddr addr,
38
ptimer_stop(s->ptimer);
39
}
40
}
41
-
42
- if ((oldval ^ value) & SYSTICK_CLKSOURCE) {
43
- systick_set_period_from_clock(s);
44
- }
45
ptimer_transaction_commit(s->ptimer);
46
break;
47
}
48
--
41
--
49
2.25.1
42
2.17.1
50
43
51
44
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
Use the named bit rather than a bare extract32.
3
With a VGICv3 KVM device, if the number of vcpus exceeds the
4
capacity of the legacy redistributor region (123 redistributors),
5
we now attempt to register a second redistributor region. Up to
6
512 redistributors can fit in this latter on top of the 123 allowed
7
by the legacy redistributor region.
4
8
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Registering this second redistributor region is possible if the
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
host kernel supports the following VGICv3 KVM device group/attribute:
7
Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>
11
KVM_DEV_ARM_VGIC_GRP_ADDR/KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION.
8
Message-id: 20220127063428.30212-5-richard.henderson@linaro.org
12
13
In case the host kernel does not support the registration of several
14
redistributor regions and the requested number of vcpus exceeds the
15
capacity of the legacy redistributor region, the GICv3 device
16
initialization fails with a proper error message and qemu exits.
17
18
At the moment the max number of vcpus still is capped by the
19
virt machine class max_cpus.
20
21
Signed-off-by: Eric Auger <eric.auger@redhat.com>
22
Reviewed-by: Andrew Jones <drjones@redhat.com>
23
Message-id: 1529072910-16156-8-git-send-email-eric.auger@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
25
---
11
target/arm/helper.c | 2 +-
26
hw/arm/virt.c | 18 +++++++++++++++++-
12
1 file changed, 1 insertion(+), 1 deletion(-)
27
1 file changed, 17 insertions(+), 1 deletion(-)
13
28
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
29
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
15
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
31
--- a/hw/arm/virt.c
17
+++ b/target/arm/helper.c
32
+++ b/hw/arm/virt.c
18
@@ -XXX,XX +XXX,XX @@ int fp_exception_el(CPUARMState *env, int cur_el)
33
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
34
SysBusDevice *gicbusdev;
35
const char *gictype;
36
int type = vms->gic_version, i;
37
+ uint32_t nb_redist_regions = 0;
38
39
gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
40
41
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
42
vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
43
uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
44
45
- qdev_prop_set_uint32(gicdev, "len-redist-region-count", 1);
46
+ nb_redist_regions = virt_gicv3_redist_region_count(vms);
47
+
48
+ qdev_prop_set_uint32(gicdev, "len-redist-region-count",
49
+ nb_redist_regions);
50
qdev_prop_set_uint32(gicdev, "redist-region-count[0]", redist0_count);
51
+
52
+ if (nb_redist_regions == 2) {
53
+ uint32_t redist1_capacity =
54
+ vms->memmap[VIRT_GIC_REDIST2].size / GICV3_REDIST_SIZE;
55
+
56
+ qdev_prop_set_uint32(gicdev, "redist-region-count[1]",
57
+ MIN(smp_cpus - redist0_count, redist1_capacity));
58
+ }
19
}
59
}
20
60
qdev_init_nofail(gicdev);
21
/* CPTR_EL3 : present in v8 */
61
gicbusdev = SYS_BUS_DEVICE(gicdev);
22
- if (extract32(env->cp15.cptr_el[3], 10, 1)) {
62
sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
23
+ if (env->cp15.cptr_el[3] & CPTR_TFP) {
63
if (type == 3) {
24
/* Trap all FP ops to EL3 */
64
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
25
return 3;
65
+ if (nb_redist_regions == 2) {
66
+ sysbus_mmio_map(gicbusdev, 2, vms->memmap[VIRT_GIC_REDIST2].base);
67
+ }
68
} else {
69
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base);
70
}
71
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
72
*/
73
if (vms->gic_version == 3) {
74
virt_max_cpus = vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
75
+ virt_max_cpus += vms->memmap[VIRT_GIC_REDIST2].size / GICV3_REDIST_SIZE;
76
} else {
77
virt_max_cpus = GIC_NCPU;
26
}
78
}
27
--
79
--
28
2.25.1
80
2.17.1
29
81
30
82
diff view generated by jsdifflib
1
From: Francisco Iglesias <francisco.iglesias@xilinx.com>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
'Or' the IRQs coming from the QSPI and QSPI DMA models. This is done for
3
This patch defines a new ECAM region located after the 256GB limit.
4
avoiding the situation where one of the models incorrectly deasserts an
5
interrupt asserted from the other model (which will result in that the IRQ
6
is lost and will not reach guest SW).
7
4
8
Signed-off-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
5
The virt machine state is augmented with a new highmem_ecam field
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
which guards the usage of this new ECAM region instead of the legacy
10
Reviewed-by: Luc Michel <luc@lmichel.fr>
7
16MB one. With the highmem ECAM region, up to 256 PCIe buses can be
11
Message-id: 20220203151742.1457-1-francisco.iglesias@xilinx.com
8
used.
9
10
Signed-off-by: Eric Auger <eric.auger@redhat.com>
11
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
12
Reviewed-by: Andrew Jones <drjones@redhat.com>
13
Message-id: 1529072910-16156-9-git-send-email-eric.auger@redhat.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
15
---
14
include/hw/arm/xlnx-zynqmp.h | 2 ++
16
include/hw/arm/virt.h | 4 ++++
15
hw/arm/xlnx-zynqmp.c | 14 ++++++++++++--
17
hw/arm/virt-acpi-build.c | 21 +++++++++++++--------
16
2 files changed, 14 insertions(+), 2 deletions(-)
18
hw/arm/virt.c | 12 ++++++++----
19
3 files changed, 25 insertions(+), 12 deletions(-)
17
20
18
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
21
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
19
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/xlnx-zynqmp.h
23
--- a/include/hw/arm/virt.h
21
+++ b/include/hw/arm/xlnx-zynqmp.h
24
+++ b/include/hw/arm/virt.h
22
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ enum {
23
#include "hw/dma/xlnx_csu_dma.h"
26
VIRT_PCIE_MMIO,
24
#include "hw/nvram/xlnx-bbram.h"
27
VIRT_PCIE_PIO,
25
#include "hw/nvram/xlnx-zynqmp-efuse.h"
28
VIRT_PCIE_ECAM,
26
+#include "hw/or-irq.h"
29
+ VIRT_PCIE_ECAM_HIGH,
27
30
VIRT_PLATFORM_BUS,
28
#define TYPE_XLNX_ZYNQMP "xlnx-zynqmp"
31
VIRT_PCIE_MMIO_HIGH,
29
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
32
VIRT_GPIO,
30
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
33
@@ -XXX,XX +XXX,XX @@ typedef struct {
31
XlnxZDMA gdma[XLNX_ZYNQMP_NUM_GDMA_CH];
34
FWCfgState *fw_cfg;
32
XlnxZDMA adma[XLNX_ZYNQMP_NUM_ADMA_CH];
35
bool secure;
33
XlnxCSUDMA qspi_dma;
36
bool highmem;
34
+ qemu_or_irq qspi_irq_orgate;
37
+ bool highmem_ecam;
35
38
bool its;
36
char *boot_cpu;
39
bool virt;
37
ARMCPU *boot_cpu_ptr;
40
int32_t gic_version;
38
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
41
@@ -XXX,XX +XXX,XX @@ typedef struct {
42
int psci_conduit;
43
} VirtMachineState;
44
45
+#define VIRT_ECAM_ID(high) (high ? VIRT_PCIE_ECAM_HIGH : VIRT_PCIE_ECAM)
46
+
47
#define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
48
#define VIRT_MACHINE(obj) \
49
OBJECT_CHECK(VirtMachineState, (obj), TYPE_VIRT_MACHINE)
50
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
39
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/arm/xlnx-zynqmp.c
52
--- a/hw/arm/virt-acpi-build.c
41
+++ b/hw/arm/xlnx-zynqmp.c
53
+++ b/hw/arm/virt-acpi-build.c
42
@@ -XXX,XX +XXX,XX @@
54
@@ -XXX,XX +XXX,XX @@ static void acpi_dsdt_add_virtio(Aml *scope,
43
#define LQSPI_ADDR 0xc0000000
44
#define QSPI_IRQ 15
45
#define QSPI_DMA_ADDR 0xff0f0800
46
+#define NUM_QSPI_IRQ_LINES 2
47
48
#define DP_ADDR 0xfd4a0000
49
#define DP_IRQ 113
50
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
51
}
52
53
object_initialize_child(obj, "qspi-dma", &s->qspi_dma, TYPE_XLNX_CSU_DMA);
54
+ object_initialize_child(obj, "qspi-irq-orgate",
55
+ &s->qspi_irq_orgate, TYPE_OR_IRQ);
56
}
55
}
57
56
58
static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
57
static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
59
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
58
- uint32_t irq, bool use_highmem)
60
gic_spi[adma_ch_intr[i]]);
59
+ uint32_t irq, bool use_highmem, bool highmem_ecam)
61
}
60
{
62
61
+ int ecam_id = VIRT_ECAM_ID(highmem_ecam);
63
+ object_property_set_int(OBJECT(&s->qspi_irq_orgate),
62
Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf;
64
+ "num-lines", NUM_QSPI_IRQ_LINES, &error_fatal);
63
int i, bus_no;
65
+ qdev_realize(DEVICE(&s->qspi_irq_orgate), NULL, &error_fatal);
64
hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
66
+ qdev_connect_gpio_out(DEVICE(&s->qspi_irq_orgate), 0, gic_spi[QSPI_IRQ]);
65
hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
67
+
66
hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
68
if (!object_property_set_link(OBJECT(&s->qspi_dma), "dma",
67
hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
69
OBJECT(system_memory), errp)) {
68
- hwaddr base_ecam = memmap[VIRT_PCIE_ECAM].base;
70
return;
69
- hwaddr size_ecam = memmap[VIRT_PCIE_ECAM].size;
71
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
70
+ hwaddr base_ecam = memmap[ecam_id].base;
72
}
71
+ hwaddr size_ecam = memmap[ecam_id].size;
73
72
int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
74
sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi_dma), 0, QSPI_DMA_ADDR);
73
75
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->qspi_dma), 0, gic_spi[QSPI_IRQ]);
74
Aml *dev = aml_device("%s", "PCI0");
76
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->qspi_dma), 0,
75
@@ -XXX,XX +XXX,XX @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
77
+ qdev_get_gpio_in(DEVICE(&s->qspi_irq_orgate), 0));
76
aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
78
77
79
if (!object_property_set_link(OBJECT(&s->qspi), "stream-connected-dma",
78
/* Declare the PCI Routing Table. */
80
OBJECT(&s->qspi_dma), errp)) {
79
- Aml *rt_pkg = aml_package(nr_pcie_buses * PCI_NUM_PINS);
81
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
80
+ Aml *rt_pkg = aml_varpackage(nr_pcie_buses * PCI_NUM_PINS);
82
}
81
for (bus_no = 0; bus_no < nr_pcie_buses; bus_no++) {
83
sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi), 0, QSPI_ADDR);
82
for (i = 0; i < PCI_NUM_PINS; i++) {
84
sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi), 1, LQSPI_ADDR);
83
int gsi = (i + bus_no) % PCI_NUM_PINS;
85
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->qspi), 0, gic_spi[QSPI_IRQ]);
84
@@ -XXX,XX +XXX,XX @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
86
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->qspi), 0,
85
Aml *dev_res0 = aml_device("%s", "RES0");
87
+ qdev_get_gpio_in(DEVICE(&s->qspi_irq_orgate), 1));
86
aml_append(dev_res0, aml_name_decl("_HID", aml_string("PNP0C02")));
88
87
crs = aml_resource_template();
89
for (i = 0; i < XLNX_ZYNQMP_NUM_QSPI_BUS; i++) {
88
- aml_append(crs, aml_memory32_fixed(base_ecam, size_ecam, AML_READ_WRITE));
90
g_autofree gchar *bus_name = g_strdup_printf("qspi%d", i);
89
+ aml_append(crs,
90
+ aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
91
+ AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, base_ecam,
92
+ base_ecam + size_ecam - 1, 0x0000, size_ecam));
93
aml_append(dev_res0, aml_name_decl("_CRS", crs));
94
aml_append(dev, dev_res0);
95
aml_append(scope, dev);
96
@@ -XXX,XX +XXX,XX @@ build_mcfg(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
97
{
98
AcpiTableMcfg *mcfg;
99
const MemMapEntry *memmap = vms->memmap;
100
+ int ecam_id = VIRT_ECAM_ID(vms->highmem_ecam);
101
int len = sizeof(*mcfg) + sizeof(mcfg->allocation[0]);
102
int mcfg_start = table_data->len;
103
104
mcfg = acpi_data_push(table_data, len);
105
- mcfg->allocation[0].address = cpu_to_le64(memmap[VIRT_PCIE_ECAM].base);
106
+ mcfg->allocation[0].address = cpu_to_le64(memmap[ecam_id].base);
107
108
/* Only a single allocation so no need to play with segments */
109
mcfg->allocation[0].pci_segment = cpu_to_le16(0);
110
mcfg->allocation[0].start_bus_number = 0;
111
- mcfg->allocation[0].end_bus_number = (memmap[VIRT_PCIE_ECAM].size
112
+ mcfg->allocation[0].end_bus_number = (memmap[ecam_id].size
113
/ PCIE_MMCFG_SIZE_MIN) - 1;
114
115
build_header(linker, table_data, (void *)(table_data->data + mcfg_start),
116
@@ -XXX,XX +XXX,XX @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
117
acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO],
118
(irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS);
119
acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + ARM_SPI_BASE),
120
- vms->highmem);
121
+ vms->highmem, vms->highmem_ecam);
122
acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO],
123
(irqmap[VIRT_GPIO] + ARM_SPI_BASE));
124
acpi_dsdt_add_power_button(scope);
125
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/hw/arm/virt.c
128
+++ b/hw/arm/virt.c
129
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry a15memmap[] = {
130
[VIRT_MEM] = { 0x40000000, RAMLIMIT_BYTES },
131
/* Additional 64 MB redist region (can contain up to 512 redistributors) */
132
[VIRT_GIC_REDIST2] = { 0x4000000000ULL, 0x4000000 },
133
+ [VIRT_PCIE_ECAM_HIGH] = { 0x4010000000ULL, 0x10000000 },
134
/* Second PCIe window, 512GB wide at the 512GB boundary */
135
[VIRT_PCIE_MMIO_HIGH] = { 0x8000000000ULL, 0x8000000000ULL },
136
};
137
@@ -XXX,XX +XXX,XX @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic)
138
hwaddr size_mmio_high = vms->memmap[VIRT_PCIE_MMIO_HIGH].size;
139
hwaddr base_pio = vms->memmap[VIRT_PCIE_PIO].base;
140
hwaddr size_pio = vms->memmap[VIRT_PCIE_PIO].size;
141
- hwaddr base_ecam = vms->memmap[VIRT_PCIE_ECAM].base;
142
- hwaddr size_ecam = vms->memmap[VIRT_PCIE_ECAM].size;
143
+ hwaddr base_ecam, size_ecam;
144
hwaddr base = base_mmio;
145
- int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
146
+ int nr_pcie_buses;
147
int irq = vms->irqmap[VIRT_PCIE];
148
MemoryRegion *mmio_alias;
149
MemoryRegion *mmio_reg;
150
@@ -XXX,XX +XXX,XX @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic)
151
MemoryRegion *ecam_reg;
152
DeviceState *dev;
153
char *nodename;
154
- int i;
155
+ int i, ecam_id;
156
PCIHostState *pci;
157
158
dev = qdev_create(NULL, TYPE_GPEX_HOST);
159
qdev_init_nofail(dev);
160
161
+ ecam_id = VIRT_ECAM_ID(vms->highmem_ecam);
162
+ base_ecam = vms->memmap[ecam_id].base;
163
+ size_ecam = vms->memmap[ecam_id].size;
164
+ nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
165
/* Map only the first size_ecam bytes of ECAM space */
166
ecam_alias = g_new0(MemoryRegion, 1);
167
ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
91
--
168
--
92
2.25.1
169
2.17.1
93
170
94
171
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
We currently miss a bunch of register resets in the device reset
3
Add virt-3.0 machine type.
4
function. This sometimes prevents the guest from rebooting after
5
a system_reset (with virtio-blk-pci). For instance, we may get
6
the following errors:
7
8
invalid STE
9
smmuv3-iommu-memory-region-0-0 translation failed for iova=0x13a9d2000(SMMU_EVT_C_BAD_STE)
10
Invalid read at addr 0x13A9D2000, size 2, region '(null)', reason: rejected
11
invalid STE
12
smmuv3-iommu-memory-region-0-0 translation failed for iova=0x13a9d2000(SMMU_EVT_C_BAD_STE)
13
Invalid write at addr 0x13A9D2000, size 2, region '(null)', reason: rejected
14
invalid STE
15
4
16
Signed-off-by: Eric Auger <eric.auger@redhat.com>
5
Signed-off-by: Eric Auger <eric.auger@redhat.com>
17
Message-id: 20220202111602.627429-1-eric.auger@redhat.com
6
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
18
Fixes: 10a83cb988 ("hw/arm/smmuv3: Skeleton")
7
Reviewed-by: Andrew Jones <drjones@redhat.com>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 1529072910-16156-10-git-send-email-eric.auger@redhat.com
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
10
---
22
hw/arm/smmuv3.c | 6 ++++++
11
hw/arm/virt.c | 15 +++++++++++++--
23
1 file changed, 6 insertions(+)
12
1 file changed, 13 insertions(+), 2 deletions(-)
24
13
25
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
14
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
26
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/smmuv3.c
16
--- a/hw/arm/virt.c
28
+++ b/hw/arm/smmuv3.c
17
+++ b/hw/arm/virt.c
29
@@ -XXX,XX +XXX,XX @@ static void smmuv3_init_regs(SMMUv3State *s)
18
@@ -XXX,XX +XXX,XX @@ type_init(machvirt_machine_init);
30
s->features = 0;
19
#define VIRT_COMPAT_2_12 \
31
s->sid_split = 0;
20
HW_COMPAT_2_12
32
s->aidr = 0x1;
21
33
+ s->cr[0] = 0;
22
-static void virt_2_12_instance_init(Object *obj)
34
+ s->cr0ack = 0;
23
+static void virt_3_0_instance_init(Object *obj)
35
+ s->irq_ctrl = 0;
24
{
36
+ s->gerror = 0;
25
VirtMachineState *vms = VIRT_MACHINE(obj);
37
+ s->gerrorn = 0;
26
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
38
+ s->statusr = 0;
27
@@ -XXX,XX +XXX,XX @@ static void virt_2_12_instance_init(Object *obj)
28
vms->irqmap = a15irqmap;
39
}
29
}
40
30
41
static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf,
31
+static void virt_machine_3_0_options(MachineClass *mc)
32
+{
33
+}
34
+DEFINE_VIRT_MACHINE_AS_LATEST(3, 0)
35
+
36
+static void virt_2_12_instance_init(Object *obj)
37
+{
38
+ virt_3_0_instance_init(obj);
39
+}
40
+
41
static void virt_machine_2_12_options(MachineClass *mc)
42
{
43
+ virt_machine_3_0_options(mc);
44
SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_12);
45
}
46
-DEFINE_VIRT_MACHINE_AS_LATEST(2, 12)
47
+DEFINE_VIRT_MACHINE(2, 12)
48
49
#define VIRT_COMPAT_2_11 \
50
HW_COMPAT_2_11
42
--
51
--
43
2.25.1
52
2.17.1
44
53
45
54
diff view generated by jsdifflib
1
We use the arm_boot_info::nb_cpus field in only one place, and that
1
From: Eric Auger <eric.auger@redhat.com>
2
place can easily get the number of CPUs locally rather than relying
3
on the board code to have set the field correctly. (At least one
4
board, xlnx-versal-virt, does not set the field despite having more
5
than one CPU.)
6
2
3
With this patch, virt-3.0 machine uses a new 256MB ECAM region
4
by default instead of the legacy 16MB one, if highmem is set
5
(LPAE supported by the guest) and (!firmware_loaded || aarch64).
6
7
Indeed aarch32 mode FW may not support this high ECAM region.
8
9
Signed-off-by: Eric Auger <eric.auger@redhat.com>
10
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
11
Reviewed-by: Andrew Jones <drjones@redhat.com>
12
Message-id: 1529072910-16156-11-git-send-email-eric.auger@redhat.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
10
Tested-by: Cédric Le Goater <clg@kaod.org>
11
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
12
Message-id: 20220127154639.2090164-16-peter.maydell@linaro.org
13
---
14
---
14
include/hw/arm/boot.h | 1 -
15
include/hw/arm/virt.h | 1 +
15
hw/arm/aspeed.c | 1 -
16
hw/arm/virt.c | 10 ++++++++++
16
hw/arm/boot.c | 7 +++----
17
2 files changed, 11 insertions(+)
17
hw/arm/exynos4_boards.c | 1 -
18
hw/arm/highbank.c | 1 -
19
hw/arm/imx25_pdk.c | 3 +--
20
hw/arm/kzm.c | 1 -
21
hw/arm/mcimx6ul-evk.c | 1 -
22
hw/arm/mcimx7d-sabre.c | 1 -
23
hw/arm/npcm7xx.c | 3 ---
24
hw/arm/orangepi.c | 4 +---
25
hw/arm/raspi.c | 1 -
26
hw/arm/realview.c | 1 -
27
hw/arm/sabrelite.c | 1 -
28
hw/arm/sbsa-ref.c | 1 -
29
hw/arm/vexpress.c | 1 -
30
hw/arm/virt.c | 1 -
31
hw/arm/xilinx_zynq.c | 1 -
32
18 files changed, 5 insertions(+), 26 deletions(-)
33
18
34
diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h
19
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
35
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/arm/boot.h
21
--- a/include/hw/arm/virt.h
37
+++ b/include/hw/arm/boot.h
22
+++ b/include/hw/arm/virt.h
38
@@ -XXX,XX +XXX,XX @@ struct arm_boot_info {
23
@@ -XXX,XX +XXX,XX @@ typedef struct {
39
hwaddr smp_loader_start;
24
bool no_pmu;
40
hwaddr smp_bootreg_addr;
25
bool claim_edge_triggered_timers;
41
hwaddr gic_cpu_if_addr;
26
bool smbios_old_sys_ver;
42
- int nb_cpus;
27
+ bool no_highmem_ecam;
43
int board_id;
28
} VirtMachineClass;
44
/* ARM machines that support the ARM Security Extensions use this field to
29
45
* control whether Linux is booted as secure(true) or non-secure(false).
30
typedef struct {
46
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/arm/aspeed.c
49
+++ b/hw/arm/aspeed.c
50
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_init(MachineState *machine)
51
52
aspeed_board_binfo.ram_size = machine->ram_size;
53
aspeed_board_binfo.loader_start = sc->memmap[ASPEED_DEV_SDRAM];
54
- aspeed_board_binfo.nb_cpus = sc->num_cpus;
55
56
if (amc->i2c_init) {
57
amc->i2c_init(bmc);
58
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/hw/arm/boot.c
61
+++ b/hw/arm/boot.c
62
@@ -XXX,XX +XXX,XX @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
63
elf_machine = EM_ARM;
64
}
65
66
- if (info->nb_cpus == 0)
67
- info->nb_cpus = 1;
68
-
69
/* Assume that raw images are linux kernels, and ELF images are not. */
70
kernel_size = arm_load_elf(info, &elf_entry, &image_low_addr,
71
&image_high_addr, elf_machine, as);
72
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
73
AddressSpace *as = arm_boot_address_space(cpu, info);
74
int boot_el;
75
CPUARMState *env = &cpu->env;
76
+ int nb_cpus = 0;
77
78
/*
79
* CPU objects (unlike devices) are not automatically reset on system
80
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
81
*/
82
for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
83
qemu_register_reset(do_cpu_reset, ARM_CPU(cs));
84
+ nb_cpus++;
85
}
86
87
/*
88
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
89
}
90
91
if (info->psci_conduit == QEMU_PSCI_CONDUIT_DISABLED &&
92
- info->is_linux && info->nb_cpus > 1) {
93
+ info->is_linux && nb_cpus > 1) {
94
/*
95
* We're booting Linux but not using PSCI, so for SMP we need
96
* to write a custom secondary CPU boot loader stub, and arrange
97
diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
98
index XXXXXXX..XXXXXXX 100644
99
--- a/hw/arm/exynos4_boards.c
100
+++ b/hw/arm/exynos4_boards.c
101
@@ -XXX,XX +XXX,XX @@ static unsigned long exynos4_board_ram_size[EXYNOS4_NUM_OF_BOARDS] = {
102
static struct arm_boot_info exynos4_board_binfo = {
103
.loader_start = EXYNOS4210_BASE_BOOT_ADDR,
104
.smp_loader_start = EXYNOS4210_SMP_BOOT_ADDR,
105
- .nb_cpus = EXYNOS4210_NCPUS,
106
.write_secondary_boot = exynos4210_write_secondary,
107
};
108
109
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
110
index XXXXXXX..XXXXXXX 100644
111
--- a/hw/arm/highbank.c
112
+++ b/hw/arm/highbank.c
113
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
114
* clear that the value is meaningless.
115
*/
116
highbank_binfo.board_id = -1;
117
- highbank_binfo.nb_cpus = smp_cpus;
118
highbank_binfo.loader_start = 0;
119
highbank_binfo.board_setup_addr = BOARD_SETUP_ADDR;
120
highbank_binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
121
diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/hw/arm/imx25_pdk.c
124
+++ b/hw/arm/imx25_pdk.c
125
@@ -XXX,XX +XXX,XX @@ static void imx25_pdk_init(MachineState *machine)
126
127
imx25_pdk_binfo.ram_size = machine->ram_size;
128
imx25_pdk_binfo.loader_start = FSL_IMX25_SDRAM0_ADDR;
129
- imx25_pdk_binfo.board_id = 1771,
130
- imx25_pdk_binfo.nb_cpus = 1;
131
+ imx25_pdk_binfo.board_id = 1771;
132
133
for (i = 0; i < FSL_IMX25_NUM_ESDHCS; i++) {
134
BusState *bus;
135
diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/hw/arm/kzm.c
138
+++ b/hw/arm/kzm.c
139
@@ -XXX,XX +XXX,XX @@ static void kzm_init(MachineState *machine)
140
}
141
142
kzm_binfo.ram_size = machine->ram_size;
143
- kzm_binfo.nb_cpus = 1;
144
145
if (!qtest_enabled()) {
146
arm_load_kernel(&s->soc.cpu, machine, &kzm_binfo);
147
diff --git a/hw/arm/mcimx6ul-evk.c b/hw/arm/mcimx6ul-evk.c
148
index XXXXXXX..XXXXXXX 100644
149
--- a/hw/arm/mcimx6ul-evk.c
150
+++ b/hw/arm/mcimx6ul-evk.c
151
@@ -XXX,XX +XXX,XX @@ static void mcimx6ul_evk_init(MachineState *machine)
152
.loader_start = FSL_IMX6UL_MMDC_ADDR,
153
.board_id = -1,
154
.ram_size = machine->ram_size,
155
- .nb_cpus = machine->smp.cpus,
156
.psci_conduit = QEMU_PSCI_CONDUIT_SMC,
157
};
158
159
diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/hw/arm/mcimx7d-sabre.c
162
+++ b/hw/arm/mcimx7d-sabre.c
163
@@ -XXX,XX +XXX,XX @@ static void mcimx7d_sabre_init(MachineState *machine)
164
.loader_start = FSL_IMX7_MMDC_ADDR,
165
.board_id = -1,
166
.ram_size = machine->ram_size,
167
- .nb_cpus = machine->smp.cpus,
168
.psci_conduit = QEMU_PSCI_CONDUIT_SMC,
169
};
170
171
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
172
index XXXXXXX..XXXXXXX 100644
173
--- a/hw/arm/npcm7xx.c
174
+++ b/hw/arm/npcm7xx.c
175
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info npcm7xx_binfo = {
176
177
void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
178
{
179
- NPCM7xxClass *sc = NPCM7XX_GET_CLASS(soc);
180
-
181
npcm7xx_binfo.ram_size = machine->ram_size;
182
- npcm7xx_binfo.nb_cpus = sc->num_cpus;
183
184
arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
185
}
186
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
187
index XXXXXXX..XXXXXXX 100644
188
--- a/hw/arm/orangepi.c
189
+++ b/hw/arm/orangepi.c
190
@@ -XXX,XX +XXX,XX @@
191
#include "hw/qdev-properties.h"
192
#include "hw/arm/allwinner-h3.h"
193
194
-static struct arm_boot_info orangepi_binfo = {
195
- .nb_cpus = AW_H3_NUM_CPUS,
196
-};
197
+static struct arm_boot_info orangepi_binfo;
198
199
static void orangepi_init(MachineState *machine)
200
{
201
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
202
index XXXXXXX..XXXXXXX 100644
203
--- a/hw/arm/raspi.c
204
+++ b/hw/arm/raspi.c
205
@@ -XXX,XX +XXX,XX @@ static void setup_boot(MachineState *machine, RaspiProcessorId processor_id,
206
207
s->binfo.board_id = MACH_TYPE_BCM2708;
208
s->binfo.ram_size = ram_size;
209
- s->binfo.nb_cpus = machine->smp.cpus;
210
211
if (processor_id <= PROCESSOR_ID_BCM2836) {
212
/*
213
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
214
index XXXXXXX..XXXXXXX 100644
215
--- a/hw/arm/realview.c
216
+++ b/hw/arm/realview.c
217
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
218
memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack);
219
220
realview_binfo.ram_size = ram_size;
221
- realview_binfo.nb_cpus = smp_cpus;
222
realview_binfo.board_id = realview_board_id[board_type];
223
realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0);
224
arm_load_kernel(ARM_CPU(first_cpu), machine, &realview_binfo);
225
diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c
226
index XXXXXXX..XXXXXXX 100644
227
--- a/hw/arm/sabrelite.c
228
+++ b/hw/arm/sabrelite.c
229
@@ -XXX,XX +XXX,XX @@ static void sabrelite_init(MachineState *machine)
230
}
231
232
sabrelite_binfo.ram_size = machine->ram_size;
233
- sabrelite_binfo.nb_cpus = machine->smp.cpus;
234
sabrelite_binfo.secure_boot = true;
235
sabrelite_binfo.write_secondary_boot = sabrelite_write_secondary;
236
sabrelite_binfo.secondary_cpu_reset_hook = sabrelite_reset_secondary;
237
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/hw/arm/sbsa-ref.c
240
+++ b/hw/arm/sbsa-ref.c
241
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
242
create_secure_ec(secure_sysmem);
243
244
sms->bootinfo.ram_size = machine->ram_size;
245
- sms->bootinfo.nb_cpus = smp_cpus;
246
sms->bootinfo.board_id = -1;
247
sms->bootinfo.loader_start = sbsa_ref_memmap[SBSA_MEM].base;
248
sms->bootinfo.get_dtb = sbsa_ref_dtb;
249
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
250
index XXXXXXX..XXXXXXX 100644
251
--- a/hw/arm/vexpress.c
252
+++ b/hw/arm/vexpress.c
253
@@ -XXX,XX +XXX,XX @@ static void vexpress_common_init(MachineState *machine)
254
}
255
256
daughterboard->bootinfo.ram_size = machine->ram_size;
257
- daughterboard->bootinfo.nb_cpus = machine->smp.cpus;
258
daughterboard->bootinfo.board_id = VEXPRESS_BOARD_ID;
259
daughterboard->bootinfo.loader_start = daughterboard->loader_start;
260
daughterboard->bootinfo.smp_loader_start = map[VE_SRAM];
261
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
31
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
262
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
263
--- a/hw/arm/virt.c
33
--- a/hw/arm/virt.c
264
+++ b/hw/arm/virt.c
34
+++ b/hw/arm/virt.c
265
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
35
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
36
int n, virt_max_cpus;
37
MemoryRegion *ram = g_new(MemoryRegion, 1);
38
bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
39
+ bool aarch64 = true;
40
41
/* We can probe only here because during property set
42
* KVM is not available yet
43
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
44
numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj),
45
&error_fatal);
46
47
+ aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL);
48
+
49
if (!vms->secure) {
50
object_property_set_bool(cpuobj, false, "has_el3", NULL);
51
}
52
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
53
create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hd(1));
266
}
54
}
267
55
268
vms->bootinfo.ram_size = machine->ram_size;
56
+ vms->highmem_ecam &= vms->highmem && (!firmware_loaded || aarch64);
269
- vms->bootinfo.nb_cpus = smp_cpus;
57
+
270
vms->bootinfo.board_id = -1;
58
create_rtc(vms, pic);
271
vms->bootinfo.loader_start = vms->memmap[VIRT_MEM].base;
59
272
vms->bootinfo.get_dtb = machvirt_dtb;
60
create_pcie(vms, pic);
273
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
61
@@ -XXX,XX +XXX,XX @@ static void virt_3_0_instance_init(Object *obj)
274
index XXXXXXX..XXXXXXX 100644
62
"Set GIC version. "
275
--- a/hw/arm/xilinx_zynq.c
63
"Valid values are 2, 3 and host", NULL);
276
+++ b/hw/arm/xilinx_zynq.c
64
277
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
65
+ vms->highmem_ecam = !vmc->no_highmem_ecam;
278
sysbus_mmio_map(busdev, 0, 0xF8007000);
66
+
279
67
if (vmc->no_its) {
280
zynq_binfo.ram_size = machine->ram_size;
68
vms->its = false;
281
- zynq_binfo.nb_cpus = 1;
69
} else {
282
zynq_binfo.board_id = 0xd32;
70
@@ -XXX,XX +XXX,XX @@ static void virt_2_12_instance_init(Object *obj)
283
zynq_binfo.loader_start = 0;
71
284
zynq_binfo.board_setup_addr = BOARD_SETUP_ADDR;
72
static void virt_machine_2_12_options(MachineClass *mc)
73
{
74
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
75
+
76
virt_machine_3_0_options(mc);
77
SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_12);
78
+ vmc->no_highmem_ecam = true;
79
}
80
DEFINE_VIRT_MACHINE(2, 12)
81
285
--
82
--
286
2.25.1
83
2.17.1
287
84
288
85
diff view generated by jsdifflib
1
Instead of setting the CPU psci-conduit and start-powered-off
1
From: Eric Auger <eric.auger@redhat.com>
2
properties in the virt board code, set the arm_boot_info psci_conduit
3
field so that the boot.c code can do it.
4
2
5
This will fix a corner case where we were incorrectly enabling PSCI
3
virt 3.0 now allows up to 512 vcpus whereas for earlier machine
6
emulation when booting guest code into EL3 because it was an ELF file
4
types, max_cpus was set to 255 and any attempt to start the
7
passed to -kernel or to the generic loader. (EL3 guest code started
5
machine with vcpus > 255 was rejected at a very early stage,
8
via -bios or -pflash was already being run with PSCI emulation
6
in vl.c/main level.
9
disabled.)
10
7
8
512 is the max supported by KVM. Anyway the actual vcpu count
9
that can be achieved depends on other parameters such as the
10
acceleration mode, the vgic version, the host kernel version.
11
Those are discovered later on.
12
13
Signed-off-by: Eric Auger <eric.auger@redhat.com>
14
Reviewed-by: Andrew Jones <drjones@redhat.com>
15
Message-id: 1529072910-16156-12-git-send-email-eric.auger@redhat.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
14
Tested-by: Cédric Le Goater <clg@kaod.org>
15
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
16
Message-id: 20220127154639.2090164-9-peter.maydell@linaro.org
17
---
17
---
18
hw/arm/virt.c | 12 +-----------
18
hw/arm/virt.c | 7 ++++---
19
1 file changed, 1 insertion(+), 11 deletions(-)
19
1 file changed, 4 insertions(+), 3 deletions(-)
20
20
21
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
21
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
22
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/virt.c
23
--- a/hw/arm/virt.c
24
+++ b/hw/arm/virt.c
24
+++ b/hw/arm/virt.c
25
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
25
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
26
object_property_set_bool(cpuobj, "has_el2", false, NULL);
26
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
27
}
27
28
28
mc->init = machvirt_init;
29
- if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
29
- /* Start max_cpus at the maximum QEMU supports. We'll further restrict
30
- object_property_set_int(cpuobj, "psci-conduit", vms->psci_conduit,
30
- * it later in machvirt_init, where we have more information about the
31
- NULL);
31
+ /* Start with max_cpus set to 512, which is the maximum supported by KVM.
32
-
32
+ * The value may be reduced later when we have more information about the
33
- /* Secondary CPUs start in PSCI powered-down state */
33
* configuration of the particular instance.
34
- if (n > 0) {
34
*/
35
- object_property_set_bool(cpuobj, "start-powered-off", true,
35
- mc->max_cpus = 255;
36
- NULL);
36
+ mc->max_cpus = 512;
37
- }
37
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_CALXEDA_XGMAC);
38
- }
38
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_AMD_XGBE);
39
-
39
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
40
if (vmc->kvm_no_adjvtime &&
40
@@ -XXX,XX +XXX,XX @@ static void virt_machine_2_12_options(MachineClass *mc)
41
object_property_find(cpuobj, "kvm-no-adjvtime")) {
41
virt_machine_3_0_options(mc);
42
object_property_set_bool(cpuobj, "kvm-no-adjvtime", true, NULL);
42
SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_12);
43
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
43
vmc->no_highmem_ecam = true;
44
vms->bootinfo.get_dtb = machvirt_dtb;
44
+ mc->max_cpus = 255;
45
vms->bootinfo.skip_dtb_autoload = true;
45
}
46
vms->bootinfo.firmware_loaded = firmware_loaded;
46
DEFINE_VIRT_MACHINE(2, 12)
47
+ vms->bootinfo.psci_conduit = vms->psci_conduit;
47
48
arm_load_kernel(ARM_CPU(first_cpu), machine, &vms->bootinfo);
49
50
vms->machine_done.notify = virt_machine_done;
51
--
48
--
52
2.25.1
49
2.17.1
53
50
54
51
diff view generated by jsdifflib
1
We want to allow the psci-conduit property to be set after realize,
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
because the parts of the code which are best placed to decide if it's
3
OK to enable QEMU's builtin PSCI emulation (the board code and the
4
arm_load_kernel() function are distant from the code which creates
5
and realizes CPUs (typically inside an SoC object's init and realize
6
method) and run afterwards.
7
2
8
Since the DEFINE_PROP_* macros don't have support for creating
3
Add the Cortex-R5F with the optional FPU enabled.
9
properties which can be changed after realize, change the property to
10
be created with object_property_add_uint32_ptr(), which is what we
11
already use in this function for creating settable-after-realize
12
properties like init-svtor and init-nsvtor.
13
4
14
Note that it doesn't conceptually make sense to change the setting of
5
Reviewed-by: KONRAD Frederic <frederic.konrad@adacore.com>
15
the property after the machine has been completely initialized,
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
beacuse this would mean that the behaviour of the machine when first
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
started would differ from its behaviour when the system is
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
subsequently reset. (It would also require the underlying state to
9
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
19
be migrated, which we don't do.)
10
Message-id: 20180529124707.3025-2-edgar.iglesias@gmail.com
20
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
24
Tested-by: Cédric Le Goater <clg@kaod.org>
25
Message-id: 20220127154639.2090164-2-peter.maydell@linaro.org
26
---
12
---
27
target/arm/cpu.c | 6 +++++-
13
target/arm/cpu.c | 9 +++++++++
28
1 file changed, 5 insertions(+), 1 deletion(-)
14
1 file changed, 9 insertions(+)
29
15
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
16
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
31
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.c
18
--- a/target/arm/cpu.c
33
+++ b/target/arm/cpu.c
19
+++ b/target/arm/cpu.c
34
@@ -XXX,XX +XXX,XX @@ void arm_cpu_post_init(Object *obj)
20
@@ -XXX,XX +XXX,XX @@ static void cortex_r5_initfn(Object *obj)
35
OBJ_PROP_FLAG_READWRITE);
21
define_arm_cp_regs(cpu, cortexr5_cp_reginfo);
36
}
22
}
37
23
38
+ /* Not DEFINE_PROP_UINT32: we want this to be settable after realize */
24
+static void cortex_r5f_initfn(Object *obj)
39
+ object_property_add_uint32_ptr(obj, "psci-conduit",
25
+{
40
+ &cpu->psci_conduit,
26
+ ARMCPU *cpu = ARM_CPU(obj);
41
+ OBJ_PROP_FLAG_READWRITE);
42
+
27
+
43
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property);
28
+ cortex_r5_initfn(obj);
44
29
+ set_feature(&cpu->env, ARM_FEATURE_VFP3);
45
if (arm_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER)) {
30
+}
46
@@ -XXX,XX +XXX,XX @@ static ObjectClass *arm_cpu_class_by_name(const char *cpu_model)
31
+
47
}
32
static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
48
33
{ .name = "L2LOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 0,
49
static Property arm_cpu_properties[] = {
34
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
50
- DEFINE_PROP_UINT32("psci-conduit", ARMCPU, psci_conduit, 0),
35
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_cpus[] = {
51
DEFINE_PROP_UINT64("midr", ARMCPU, midr, 0),
36
{ .name = "cortex-m33", .initfn = cortex_m33_initfn,
52
DEFINE_PROP_UINT64("mp-affinity", ARMCPU,
37
.class_init = arm_v7m_class_init },
53
mp_affinity, ARM64_AFFINITY_INVALID),
38
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
39
+ { .name = "cortex-r5f", .initfn = cortex_r5f_initfn },
40
{ .name = "cortex-a7", .initfn = cortex_a7_initfn },
41
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
42
{ .name = "cortex-a9", .initfn = cortex_a9_initfn },
54
--
43
--
55
2.25.1
44
2.17.1
56
45
57
46
diff view generated by jsdifflib
1
Change the Xilinx ZynqMP-based board xlnx-zcu102 to use the new
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
boot.c functionality to allow us to enable psci-conduit only if
3
the guest is being booted in EL1 or EL2, so that if the user runs
4
guest EL3 firmware code our PSCI emulation doesn't get in its
5
way.
6
2
7
To do this we stop setting the psci-conduit property on the CPU
3
The ZynqMP has Cortex-R5Fs with the optional FPU enabled.
8
objects in the SoC code, and instead set the psci_conduit field in
9
the arm_boot_info struct to tell the common boot loader code that
10
we'd like PSCI if the guest is starting at an EL that it makes
11
sense with.
12
4
13
Note that this means that EL3 guest code will have no way
5
Reviewed-by: KONRAD Frederic <frederic.konrad@adacore.com>
14
to power on secondary cores, because we don't model any
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
15
kind of power controller that does that on this SoC.
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Message-id: 20180529124707.3025-3-edgar.iglesias@gmail.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
21
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
22
Tested-by: Cédric Le Goater <clg@kaod.org>
23
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
24
Acked-by: Richard Henderson <richard.henderson@linaro.org>
25
Message-id: 20220127154639.2090164-7-peter.maydell@linaro.org
26
---
12
---
27
hw/arm/xlnx-zcu102.c | 1 +
13
hw/arm/xlnx-zcu102.c | 2 +-
28
hw/arm/xlnx-zynqmp.c | 11 ++++++-----
14
hw/arm/xlnx-zynqmp.c | 2 +-
29
2 files changed, 7 insertions(+), 5 deletions(-)
15
2 files changed, 2 insertions(+), 2 deletions(-)
30
16
31
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
17
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
32
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/arm/xlnx-zcu102.c
19
--- a/hw/arm/xlnx-zcu102.c
34
+++ b/hw/arm/xlnx-zcu102.c
20
+++ b/hw/arm/xlnx-zcu102.c
35
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
21
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
36
s->binfo.ram_size = ram_size;
22
{
37
s->binfo.loader_start = 0;
23
MachineClass *mc = MACHINE_CLASS(oc);
38
s->binfo.modify_dtb = zcu102_modify_dtb;
24
39
+ s->binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
25
- mc->desc = "Xilinx ZynqMP ZCU102 board with 4xA53s and 2xR5s based on " \
40
arm_load_kernel(s->soc.boot_cpu_ptr, machine, &s->binfo);
26
+ mc->desc = "Xilinx ZynqMP ZCU102 board with 4xA53s and 2xR5Fs based on " \
41
}
27
"the value of smp";
42
28
mc->init = xlnx_zcu102_init;
29
mc->block_default_type = IF_IDE;
43
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
30
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
44
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/arm/xlnx-zynqmp.c
32
--- a/hw/arm/xlnx-zynqmp.c
46
+++ b/hw/arm/xlnx-zynqmp.c
33
+++ b/hw/arm/xlnx-zynqmp.c
47
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_create_rpu(MachineState *ms, XlnxZynqMPState *s,
34
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_create_rpu(XlnxZynqMPState *s, const char *boot_cpu,
48
35
char *name;
49
name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i]));
36
50
if (strcmp(name, boot_cpu)) {
37
object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]),
51
- /* Secondary CPUs start in PSCI powered-down state */
38
- "cortex-r5-" TYPE_ARM_CPU);
52
+ /*
39
+ "cortex-r5f-" TYPE_ARM_CPU);
53
+ * Secondary CPUs start in powered-down state.
40
object_property_add_child(OBJECT(s), "rpu-cpu[*]",
54
+ */
41
OBJECT(&s->rpu_cpu[i]), &error_abort);
55
object_property_set_bool(OBJECT(&s->rpu_cpu[i]),
42
56
"start-powered-off", true, &error_abort);
57
} else {
58
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
59
for (i = 0; i < num_apus; i++) {
60
const char *name;
61
62
- object_property_set_int(OBJECT(&s->apu_cpu[i]), "psci-conduit",
63
- QEMU_PSCI_CONDUIT_SMC, &error_abort);
64
-
65
name = object_get_canonical_path_component(OBJECT(&s->apu_cpu[i]));
66
if (strcmp(name, boot_cpu)) {
67
- /* Secondary CPUs start in PSCI powered-down state */
68
+ /*
69
+ * Secondary CPUs start in powered-down state.
70
+ */
71
object_property_set_bool(OBJECT(&s->apu_cpu[i]),
72
"start-powered-off", true, &error_abort);
73
} else {
74
--
43
--
75
2.25.1
44
2.17.1
76
45
77
46
diff view generated by jsdifflib
1
From: Kevin Townsend <kevin.townsend@linaro.org>
1
Implement the Arm TrustZone Memory Protection Controller, which sits
2
in front of RAM and allows secure software to configure it to either
3
pass through or reject transactions.
2
4
3
This commit adds emulation of the magnetometer on the LSM303DLHC.
5
We implement the MPC as a QEMU IOMMU, which will direct transactions
4
It allows the magnetometer's X, Y and Z outputs to be set via the
6
either through to the devices and memory behind it or to a special
5
mag-x, mag-y and mag-z properties, as well as the 12-bit
7
"never works" AddressSpace if they are blocked.
6
temperature output via the temperature property. Sensor can be
7
enabled with 'CONFIG_LSM303DLHC_MAG=y'.
8
8
9
Signed-off-by: Kevin Townsend <kevin.townsend@linaro.org>
9
This initial commit implements the skeleton of the device:
10
Message-id: 20220130095032.35392-1-kevin.townsend@linaro.org
10
* it always permits accesses
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
* it doesn't implement most of the registers
12
* it doesn't implement the interrupt or other behaviour
13
for blocked transactions
14
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
17
Reviewed-by: Eric Auger <eric.auger@redhat.com>
18
Message-id: 20180620132032.28865-2-peter.maydell@linaro.org
13
---
19
---
14
hw/sensor/lsm303dlhc_mag.c | 556 ++++++++++++++++++++++++++++++
20
hw/misc/Makefile.objs | 1 +
15
tests/qtest/lsm303dlhc-mag-test.c | 148 ++++++++
21
include/hw/misc/tz-mpc.h | 70 ++++++
16
hw/sensor/Kconfig | 4 +
22
hw/misc/tz-mpc.c | 399 ++++++++++++++++++++++++++++++++
17
hw/sensor/meson.build | 1 +
23
MAINTAINERS | 2 +
18
tests/qtest/meson.build | 1 +
24
default-configs/arm-softmmu.mak | 1 +
19
5 files changed, 710 insertions(+)
25
hw/misc/trace-events | 7 +
20
create mode 100644 hw/sensor/lsm303dlhc_mag.c
26
6 files changed, 480 insertions(+)
21
create mode 100644 tests/qtest/lsm303dlhc-mag-test.c
27
create mode 100644 include/hw/misc/tz-mpc.h
28
create mode 100644 hw/misc/tz-mpc.c
22
29
23
diff --git a/hw/sensor/lsm303dlhc_mag.c b/hw/sensor/lsm303dlhc_mag.c
30
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/misc/Makefile.objs
33
+++ b/hw/misc/Makefile.objs
34
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MIPS_ITU) += mips_itu.o
35
obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
36
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
37
38
+obj-$(CONFIG_TZ_MPC) += tz-mpc.o
39
obj-$(CONFIG_TZ_PPC) += tz-ppc.o
40
obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
41
42
diff --git a/include/hw/misc/tz-mpc.h b/include/hw/misc/tz-mpc.h
24
new file mode 100644
43
new file mode 100644
25
index XXXXXXX..XXXXXXX
44
index XXXXXXX..XXXXXXX
26
--- /dev/null
45
--- /dev/null
27
+++ b/hw/sensor/lsm303dlhc_mag.c
46
+++ b/include/hw/misc/tz-mpc.h
28
@@ -XXX,XX +XXX,XX @@
47
@@ -XXX,XX +XXX,XX @@
29
+/*
48
+/*
30
+ * LSM303DLHC I2C magnetometer.
49
+ * ARM AHB5 TrustZone Memory Protection Controller emulation
31
+ *
50
+ *
32
+ * Copyright (C) 2021 Linaro Ltd.
51
+ * Copyright (c) 2018 Linaro Limited
33
+ * Written by Kevin Townsend <kevin.townsend@linaro.org>
52
+ * Written by Peter Maydell
34
+ *
53
+ *
35
+ * Based on: https://www.st.com/resource/en/datasheet/lsm303dlhc.pdf
54
+ * This program is free software; you can redistribute it and/or modify
36
+ *
55
+ * it under the terms of the GNU General Public License version 2 or
37
+ * SPDX-License-Identifier: GPL-2.0-or-later
56
+ * (at your option) any later version.
38
+ */
57
+ */
39
+
58
+
40
+/*
59
+/* This is a model of the TrustZone memory protection controller (MPC).
41
+ * The I2C address associated with this device is set on the command-line when
60
+ * It is documented in the ARM CoreLink SIE-200 System IP for Embedded TRM
42
+ * initialising the machine, but the following address is standard: 0x1E.
61
+ * (DDI 0571G):
43
+ *
62
+ * https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g
44
+ * Get and set functions for 'mag-x', 'mag-y' and 'mag-z' assume that
63
+ *
45
+ * 1 = 0.001 uT. (NOTE the 1 gauss = 100 uT, so setting a value of 100,000
64
+ * The MPC sits in front of memory and allows secure software to
46
+ * would be equal to 1 gauss or 100 uT.)
65
+ * configure it to either pass through or reject transactions.
47
+ *
66
+ * Rejected transactions may be configured to either be aborted, or to
48
+ * Get and set functions for 'temperature' assume that 1 = 0.001 C, so 23.6 C
67
+ * behave as RAZ/WI. An interrupt can be signalled for a rejected transaction.
49
+ * would be equal to 23600.
68
+ *
69
+ * The MPC has a register interface which the guest uses to configure it.
70
+ *
71
+ * QEMU interface:
72
+ * + sysbus MMIO region 0: MemoryRegion for the MPC's config registers
73
+ * + sysbus MMIO region 1: MemoryRegion for the upstream end of the MPC
74
+ * + Property "downstream": MemoryRegion defining the downstream memory
75
+ * + Named GPIO output "irq": set for a transaction-failed interrupt
50
+ */
76
+ */
51
+
77
+
52
+#include "qemu/osdep.h"
78
+#ifndef TZ_MPC_H
53
+#include "hw/i2c/i2c.h"
79
+#define TZ_MPC_H
54
+#include "migration/vmstate.h"
80
+
55
+#include "qapi/error.h"
81
+#include "hw/sysbus.h"
56
+#include "qapi/visitor.h"
82
+
57
+#include "qemu/module.h"
83
+#define TYPE_TZ_MPC "tz-mpc"
58
+#include "qemu/log.h"
84
+#define TZ_MPC(obj) OBJECT_CHECK(TZMPC, (obj), TYPE_TZ_MPC)
59
+#include "qemu/bswap.h"
85
+
60
+
86
+#define TZ_NUM_PORTS 16
61
+enum LSM303DLHCMagReg {
87
+
62
+ LSM303DLHC_MAG_REG_CRA = 0x00,
88
+#define TYPE_TZ_MPC_IOMMU_MEMORY_REGION "tz-mpc-iommu-memory-region"
63
+ LSM303DLHC_MAG_REG_CRB = 0x01,
89
+
64
+ LSM303DLHC_MAG_REG_MR = 0x02,
90
+typedef struct TZMPC TZMPC;
65
+ LSM303DLHC_MAG_REG_OUT_X_H = 0x03,
91
+
66
+ LSM303DLHC_MAG_REG_OUT_X_L = 0x04,
92
+struct TZMPC {
67
+ LSM303DLHC_MAG_REG_OUT_Z_H = 0x05,
93
+ /*< private >*/
68
+ LSM303DLHC_MAG_REG_OUT_Z_L = 0x06,
94
+ SysBusDevice parent_obj;
69
+ LSM303DLHC_MAG_REG_OUT_Y_H = 0x07,
95
+
70
+ LSM303DLHC_MAG_REG_OUT_Y_L = 0x08,
96
+ /*< public >*/
71
+ LSM303DLHC_MAG_REG_SR = 0x09,
97
+
72
+ LSM303DLHC_MAG_REG_IRA = 0x0A,
98
+ qemu_irq irq;
73
+ LSM303DLHC_MAG_REG_IRB = 0x0B,
99
+
74
+ LSM303DLHC_MAG_REG_IRC = 0x0C,
100
+ /* Properties */
75
+ LSM303DLHC_MAG_REG_TEMP_OUT_H = 0x31,
101
+ MemoryRegion *downstream;
76
+ LSM303DLHC_MAG_REG_TEMP_OUT_L = 0x32
102
+
77
+};
103
+ hwaddr blocksize;
78
+
104
+ uint32_t blk_max;
79
+typedef struct LSM303DLHCMagState {
105
+
80
+ I2CSlave parent_obj;
106
+ /* MemoryRegions exposed to user */
81
+ uint8_t cra;
107
+ MemoryRegion regmr;
82
+ uint8_t crb;
108
+ IOMMUMemoryRegion upstream;
83
+ uint8_t mr;
109
+
84
+ int16_t x;
110
+ /* MemoryRegion used internally */
85
+ int16_t z;
111
+ MemoryRegion blocked_io;
86
+ int16_t y;
112
+
87
+ int16_t x_lock;
113
+ AddressSpace downstream_as;
88
+ int16_t z_lock;
114
+ AddressSpace blocked_io_as;
89
+ int16_t y_lock;
115
+};
90
+ uint8_t sr;
116
+
91
+ uint8_t ira;
117
+#endif
92
+ uint8_t irb;
118
diff --git a/hw/misc/tz-mpc.c b/hw/misc/tz-mpc.c
93
+ uint8_t irc;
94
+ int16_t temperature;
95
+ int16_t temperature_lock;
96
+ uint8_t len;
97
+ uint8_t buf;
98
+ uint8_t pointer;
99
+} LSM303DLHCMagState;
100
+
101
+#define TYPE_LSM303DLHC_MAG "lsm303dlhc_mag"
102
+OBJECT_DECLARE_SIMPLE_TYPE(LSM303DLHCMagState, LSM303DLHC_MAG)
103
+
104
+/*
105
+ * Conversion factor from Gauss to sensor values for each GN gain setting,
106
+ * in units "lsb per Gauss" (see data sheet table 3). There is no documented
107
+ * behaviour if the GN setting in CRB is incorrectly set to 0b000;
108
+ * we arbitrarily make it the same as 0b001.
109
+ */
110
+uint32_t xy_gain[] = { 1100, 1100, 855, 670, 450, 400, 330, 230 };
111
+uint32_t z_gain[] = { 980, 980, 760, 600, 400, 355, 295, 205 };
112
+
113
+static void lsm303dlhc_mag_get_x(Object *obj, Visitor *v, const char *name,
114
+ void *opaque, Error **errp)
115
+{
116
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(obj);
117
+ int gm = extract32(s->crb, 5, 3);
118
+
119
+ /* Convert to uT where 1000 = 1 uT. Conversion factor depends on gain. */
120
+ int64_t value = muldiv64(s->x, 100000, xy_gain[gm]);
121
+ visit_type_int(v, name, &value, errp);
122
+}
123
+
124
+static void lsm303dlhc_mag_get_y(Object *obj, Visitor *v, const char *name,
125
+ void *opaque, Error **errp)
126
+{
127
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(obj);
128
+ int gm = extract32(s->crb, 5, 3);
129
+
130
+ /* Convert to uT where 1000 = 1 uT. Conversion factor depends on gain. */
131
+ int64_t value = muldiv64(s->y, 100000, xy_gain[gm]);
132
+ visit_type_int(v, name, &value, errp);
133
+}
134
+
135
+static void lsm303dlhc_mag_get_z(Object *obj, Visitor *v, const char *name,
136
+ void *opaque, Error **errp)
137
+{
138
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(obj);
139
+ int gm = extract32(s->crb, 5, 3);
140
+
141
+ /* Convert to uT where 1000 = 1 uT. Conversion factor depends on gain. */
142
+ int64_t value = muldiv64(s->z, 100000, z_gain[gm]);
143
+ visit_type_int(v, name, &value, errp);
144
+}
145
+
146
+static void lsm303dlhc_mag_set_x(Object *obj, Visitor *v, const char *name,
147
+ void *opaque, Error **errp)
148
+{
149
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(obj);
150
+ int64_t value;
151
+ int64_t reg;
152
+ int gm = extract32(s->crb, 5, 3);
153
+
154
+ if (!visit_type_int(v, name, &value, errp)) {
155
+ return;
156
+ }
157
+
158
+ reg = muldiv64(value, xy_gain[gm], 100000);
159
+
160
+ /* Make sure we are within a 12-bit limit. */
161
+ if (reg > 2047 || reg < -2048) {
162
+ error_setg(errp, "value %" PRId64 " out of register's range", value);
163
+ return;
164
+ }
165
+
166
+ s->x = (int16_t)reg;
167
+}
168
+
169
+static void lsm303dlhc_mag_set_y(Object *obj, Visitor *v, const char *name,
170
+ void *opaque, Error **errp)
171
+{
172
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(obj);
173
+ int64_t value;
174
+ int64_t reg;
175
+ int gm = extract32(s->crb, 5, 3);
176
+
177
+ if (!visit_type_int(v, name, &value, errp)) {
178
+ return;
179
+ }
180
+
181
+ reg = muldiv64(value, xy_gain[gm], 100000);
182
+
183
+ /* Make sure we are within a 12-bit limit. */
184
+ if (reg > 2047 || reg < -2048) {
185
+ error_setg(errp, "value %" PRId64 " out of register's range", value);
186
+ return;
187
+ }
188
+
189
+ s->y = (int16_t)reg;
190
+}
191
+
192
+static void lsm303dlhc_mag_set_z(Object *obj, Visitor *v, const char *name,
193
+ void *opaque, Error **errp)
194
+{
195
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(obj);
196
+ int64_t value;
197
+ int64_t reg;
198
+ int gm = extract32(s->crb, 5, 3);
199
+
200
+ if (!visit_type_int(v, name, &value, errp)) {
201
+ return;
202
+ }
203
+
204
+ reg = muldiv64(value, z_gain[gm], 100000);
205
+
206
+ /* Make sure we are within a 12-bit limit. */
207
+ if (reg > 2047 || reg < -2048) {
208
+ error_setg(errp, "value %" PRId64 " out of register's range", value);
209
+ return;
210
+ }
211
+
212
+ s->z = (int16_t)reg;
213
+}
214
+
215
+/*
216
+ * Get handler for the temperature property.
217
+ */
218
+static void lsm303dlhc_mag_get_temperature(Object *obj, Visitor *v,
219
+ const char *name, void *opaque,
220
+ Error **errp)
221
+{
222
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(obj);
223
+ int64_t value;
224
+
225
+ /* Convert to 1 lsb = 0.125 C to 1 = 0.001 C for 'temperature' property. */
226
+ value = s->temperature * 125;
227
+
228
+ visit_type_int(v, name, &value, errp);
229
+}
230
+
231
+/*
232
+ * Set handler for the temperature property.
233
+ */
234
+static void lsm303dlhc_mag_set_temperature(Object *obj, Visitor *v,
235
+ const char *name, void *opaque,
236
+ Error **errp)
237
+{
238
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(obj);
239
+ int64_t value;
240
+
241
+ if (!visit_type_int(v, name, &value, errp)) {
242
+ return;
243
+ }
244
+
245
+ /* Input temperature is in 0.001 C units. Convert to 1 lsb = 0.125 C. */
246
+ value /= 125;
247
+
248
+ if (value > 2047 || value < -2048) {
249
+ error_setg(errp, "value %" PRId64 " lsb is out of range", value);
250
+ return;
251
+ }
252
+
253
+ s->temperature = (int16_t)value;
254
+}
255
+
256
+/*
257
+ * Callback handler whenever a 'I2C_START_RECV' (read) event is received.
258
+ */
259
+static void lsm303dlhc_mag_read(LSM303DLHCMagState *s)
260
+{
261
+ /*
262
+ * Set the LOCK bit whenever a new read attempt is made. This will be
263
+ * cleared in I2C_FINISH. Note that DRDY is always set to 1 in this driver.
264
+ */
265
+ s->sr = 0x3;
266
+
267
+ /*
268
+ * Copy the current X/Y/Z and temp. values into the locked registers so
269
+ * that 'mag-x', 'mag-y', 'mag-z' and 'temperature' can continue to be
270
+ * updated via QOM, etc., without corrupting the current read event.
271
+ */
272
+ s->x_lock = s->x;
273
+ s->z_lock = s->z;
274
+ s->y_lock = s->y;
275
+ s->temperature_lock = s->temperature;
276
+}
277
+
278
+/*
279
+ * Callback handler whenever a 'I2C_FINISH' event is received.
280
+ */
281
+static void lsm303dlhc_mag_finish(LSM303DLHCMagState *s)
282
+{
283
+ /*
284
+ * Clear the LOCK bit when the read attempt terminates.
285
+ * This bit is initially set in the I2C_START_RECV handler.
286
+ */
287
+ s->sr = 0x1;
288
+}
289
+
290
+/*
291
+ * Callback handler when a device attempts to write to a register.
292
+ */
293
+static void lsm303dlhc_mag_write(LSM303DLHCMagState *s)
294
+{
295
+ switch (s->pointer) {
296
+ case LSM303DLHC_MAG_REG_CRA:
297
+ s->cra = s->buf;
298
+ break;
299
+ case LSM303DLHC_MAG_REG_CRB:
300
+ /* Make sure gain is at least 1, falling back to 1 on an error. */
301
+ if (s->buf >> 5 == 0) {
302
+ s->buf = 1 << 5;
303
+ }
304
+ s->crb = s->buf;
305
+ break;
306
+ case LSM303DLHC_MAG_REG_MR:
307
+ s->mr = s->buf;
308
+ break;
309
+ case LSM303DLHC_MAG_REG_SR:
310
+ s->sr = s->buf;
311
+ break;
312
+ case LSM303DLHC_MAG_REG_IRA:
313
+ s->ira = s->buf;
314
+ break;
315
+ case LSM303DLHC_MAG_REG_IRB:
316
+ s->irb = s->buf;
317
+ break;
318
+ case LSM303DLHC_MAG_REG_IRC:
319
+ s->irc = s->buf;
320
+ break;
321
+ default:
322
+ qemu_log_mask(LOG_GUEST_ERROR, "reg is read-only: 0x%02X", s->buf);
323
+ break;
324
+ }
325
+}
326
+
327
+/*
328
+ * Low-level master-to-slave transaction handler.
329
+ */
330
+static int lsm303dlhc_mag_send(I2CSlave *i2c, uint8_t data)
331
+{
332
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(i2c);
333
+
334
+ if (s->len == 0) {
335
+ /* First byte is the reg pointer */
336
+ s->pointer = data;
337
+ s->len++;
338
+ } else if (s->len == 1) {
339
+ /* Second byte is the new register value. */
340
+ s->buf = data;
341
+ lsm303dlhc_mag_write(s);
342
+ } else {
343
+ g_assert_not_reached();
344
+ }
345
+
346
+ return 0;
347
+}
348
+
349
+/*
350
+ * Low-level slave-to-master transaction handler (read attempts).
351
+ */
352
+static uint8_t lsm303dlhc_mag_recv(I2CSlave *i2c)
353
+{
354
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(i2c);
355
+ uint8_t resp;
356
+
357
+ switch (s->pointer) {
358
+ case LSM303DLHC_MAG_REG_CRA:
359
+ resp = s->cra;
360
+ break;
361
+ case LSM303DLHC_MAG_REG_CRB:
362
+ resp = s->crb;
363
+ break;
364
+ case LSM303DLHC_MAG_REG_MR:
365
+ resp = s->mr;
366
+ break;
367
+ case LSM303DLHC_MAG_REG_OUT_X_H:
368
+ resp = (uint8_t)(s->x_lock >> 8);
369
+ break;
370
+ case LSM303DLHC_MAG_REG_OUT_X_L:
371
+ resp = (uint8_t)(s->x_lock);
372
+ break;
373
+ case LSM303DLHC_MAG_REG_OUT_Z_H:
374
+ resp = (uint8_t)(s->z_lock >> 8);
375
+ break;
376
+ case LSM303DLHC_MAG_REG_OUT_Z_L:
377
+ resp = (uint8_t)(s->z_lock);
378
+ break;
379
+ case LSM303DLHC_MAG_REG_OUT_Y_H:
380
+ resp = (uint8_t)(s->y_lock >> 8);
381
+ break;
382
+ case LSM303DLHC_MAG_REG_OUT_Y_L:
383
+ resp = (uint8_t)(s->y_lock);
384
+ break;
385
+ case LSM303DLHC_MAG_REG_SR:
386
+ resp = s->sr;
387
+ break;
388
+ case LSM303DLHC_MAG_REG_IRA:
389
+ resp = s->ira;
390
+ break;
391
+ case LSM303DLHC_MAG_REG_IRB:
392
+ resp = s->irb;
393
+ break;
394
+ case LSM303DLHC_MAG_REG_IRC:
395
+ resp = s->irc;
396
+ break;
397
+ case LSM303DLHC_MAG_REG_TEMP_OUT_H:
398
+ /* Check if the temperature sensor is enabled or not (CRA & 0x80). */
399
+ if (s->cra & 0x80) {
400
+ resp = (uint8_t)(s->temperature_lock >> 8);
401
+ } else {
402
+ resp = 0;
403
+ }
404
+ break;
405
+ case LSM303DLHC_MAG_REG_TEMP_OUT_L:
406
+ if (s->cra & 0x80) {
407
+ resp = (uint8_t)(s->temperature_lock & 0xff);
408
+ } else {
409
+ resp = 0;
410
+ }
411
+ break;
412
+ default:
413
+ resp = 0;
414
+ break;
415
+ }
416
+
417
+ /*
418
+ * The address pointer on the LSM303DLHC auto-increments whenever a byte
419
+ * is read, without the master device having to request the next address.
420
+ *
421
+ * The auto-increment process has the following logic:
422
+ *
423
+ * - if (s->pointer == 8) then s->pointer = 3
424
+ * - else: if (s->pointer == 12) then s->pointer = 0
425
+ * - else: s->pointer += 1
426
+ *
427
+ * Reading an invalid address return 0.
428
+ */
429
+ if (s->pointer == LSM303DLHC_MAG_REG_OUT_Y_L) {
430
+ s->pointer = LSM303DLHC_MAG_REG_OUT_X_H;
431
+ } else if (s->pointer == LSM303DLHC_MAG_REG_IRC) {
432
+ s->pointer = LSM303DLHC_MAG_REG_CRA;
433
+ } else {
434
+ s->pointer++;
435
+ }
436
+
437
+ return resp;
438
+}
439
+
440
+/*
441
+ * Bus state change handler.
442
+ */
443
+static int lsm303dlhc_mag_event(I2CSlave *i2c, enum i2c_event event)
444
+{
445
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(i2c);
446
+
447
+ switch (event) {
448
+ case I2C_START_SEND:
449
+ break;
450
+ case I2C_START_RECV:
451
+ lsm303dlhc_mag_read(s);
452
+ break;
453
+ case I2C_FINISH:
454
+ lsm303dlhc_mag_finish(s);
455
+ break;
456
+ case I2C_NACK:
457
+ break;
458
+ }
459
+
460
+ s->len = 0;
461
+ return 0;
462
+}
463
+
464
+/*
465
+ * Device data description using VMSTATE macros.
466
+ */
467
+static const VMStateDescription vmstate_lsm303dlhc_mag = {
468
+ .name = "LSM303DLHC_MAG",
469
+ .version_id = 0,
470
+ .minimum_version_id = 0,
471
+ .fields = (VMStateField[]) {
472
+
473
+ VMSTATE_I2C_SLAVE(parent_obj, LSM303DLHCMagState),
474
+ VMSTATE_UINT8(len, LSM303DLHCMagState),
475
+ VMSTATE_UINT8(buf, LSM303DLHCMagState),
476
+ VMSTATE_UINT8(pointer, LSM303DLHCMagState),
477
+ VMSTATE_UINT8(cra, LSM303DLHCMagState),
478
+ VMSTATE_UINT8(crb, LSM303DLHCMagState),
479
+ VMSTATE_UINT8(mr, LSM303DLHCMagState),
480
+ VMSTATE_INT16(x, LSM303DLHCMagState),
481
+ VMSTATE_INT16(z, LSM303DLHCMagState),
482
+ VMSTATE_INT16(y, LSM303DLHCMagState),
483
+ VMSTATE_INT16(x_lock, LSM303DLHCMagState),
484
+ VMSTATE_INT16(z_lock, LSM303DLHCMagState),
485
+ VMSTATE_INT16(y_lock, LSM303DLHCMagState),
486
+ VMSTATE_UINT8(sr, LSM303DLHCMagState),
487
+ VMSTATE_UINT8(ira, LSM303DLHCMagState),
488
+ VMSTATE_UINT8(irb, LSM303DLHCMagState),
489
+ VMSTATE_UINT8(irc, LSM303DLHCMagState),
490
+ VMSTATE_INT16(temperature, LSM303DLHCMagState),
491
+ VMSTATE_INT16(temperature_lock, LSM303DLHCMagState),
492
+ VMSTATE_END_OF_LIST()
493
+ }
494
+};
495
+
496
+/*
497
+ * Put the device into post-reset default state.
498
+ */
499
+static void lsm303dlhc_mag_default_cfg(LSM303DLHCMagState *s)
500
+{
501
+ /* Set the device into is default reset state. */
502
+ s->len = 0;
503
+ s->pointer = 0; /* Current register. */
504
+ s->buf = 0; /* Shared buffer. */
505
+ s->cra = 0x10; /* Temp Enabled = 0, Data Rate = 15.0 Hz. */
506
+ s->crb = 0x20; /* Gain = +/- 1.3 Gauss. */
507
+ s->mr = 0x3; /* Operating Mode = Sleep. */
508
+ s->x = 0;
509
+ s->z = 0;
510
+ s->y = 0;
511
+ s->x_lock = 0;
512
+ s->z_lock = 0;
513
+ s->y_lock = 0;
514
+ s->sr = 0x1; /* DRDY = 1. */
515
+ s->ira = 0x48;
516
+ s->irb = 0x34;
517
+ s->irc = 0x33;
518
+ s->temperature = 0; /* Default to 0 degrees C (0/8 lsb = 0 C). */
519
+ s->temperature_lock = 0;
520
+}
521
+
522
+/*
523
+ * Callback handler when DeviceState 'reset' is set to true.
524
+ */
525
+static void lsm303dlhc_mag_reset(DeviceState *dev)
526
+{
527
+ I2CSlave *i2c = I2C_SLAVE(dev);
528
+ LSM303DLHCMagState *s = LSM303DLHC_MAG(i2c);
529
+
530
+ /* Set the device into its default reset state. */
531
+ lsm303dlhc_mag_default_cfg(s);
532
+}
533
+
534
+/*
535
+ * Initialisation of any public properties.
536
+ */
537
+static void lsm303dlhc_mag_initfn(Object *obj)
538
+{
539
+ object_property_add(obj, "mag-x", "int",
540
+ lsm303dlhc_mag_get_x,
541
+ lsm303dlhc_mag_set_x, NULL, NULL);
542
+
543
+ object_property_add(obj, "mag-y", "int",
544
+ lsm303dlhc_mag_get_y,
545
+ lsm303dlhc_mag_set_y, NULL, NULL);
546
+
547
+ object_property_add(obj, "mag-z", "int",
548
+ lsm303dlhc_mag_get_z,
549
+ lsm303dlhc_mag_set_z, NULL, NULL);
550
+
551
+ object_property_add(obj, "temperature", "int",
552
+ lsm303dlhc_mag_get_temperature,
553
+ lsm303dlhc_mag_set_temperature, NULL, NULL);
554
+}
555
+
556
+/*
557
+ * Set the virtual method pointers (bus state change, tx/rx, etc.).
558
+ */
559
+static void lsm303dlhc_mag_class_init(ObjectClass *klass, void *data)
560
+{
561
+ DeviceClass *dc = DEVICE_CLASS(klass);
562
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
563
+
564
+ dc->reset = lsm303dlhc_mag_reset;
565
+ dc->vmsd = &vmstate_lsm303dlhc_mag;
566
+ k->event = lsm303dlhc_mag_event;
567
+ k->recv = lsm303dlhc_mag_recv;
568
+ k->send = lsm303dlhc_mag_send;
569
+}
570
+
571
+static const TypeInfo lsm303dlhc_mag_info = {
572
+ .name = TYPE_LSM303DLHC_MAG,
573
+ .parent = TYPE_I2C_SLAVE,
574
+ .instance_size = sizeof(LSM303DLHCMagState),
575
+ .instance_init = lsm303dlhc_mag_initfn,
576
+ .class_init = lsm303dlhc_mag_class_init,
577
+};
578
+
579
+static void lsm303dlhc_mag_register_types(void)
580
+{
581
+ type_register_static(&lsm303dlhc_mag_info);
582
+}
583
+
584
+type_init(lsm303dlhc_mag_register_types)
585
diff --git a/tests/qtest/lsm303dlhc-mag-test.c b/tests/qtest/lsm303dlhc-mag-test.c
586
new file mode 100644
119
new file mode 100644
587
index XXXXXXX..XXXXXXX
120
index XXXXXXX..XXXXXXX
588
--- /dev/null
121
--- /dev/null
589
+++ b/tests/qtest/lsm303dlhc-mag-test.c
122
+++ b/hw/misc/tz-mpc.c
590
@@ -XXX,XX +XXX,XX @@
123
@@ -XXX,XX +XXX,XX @@
591
+/*
124
+/*
592
+ * QTest testcase for the LSM303DLHC I2C magnetometer
125
+ * ARM AHB5 TrustZone Memory Protection Controller emulation
593
+ *
126
+ *
594
+ * Copyright (C) 2021 Linaro Ltd.
127
+ * Copyright (c) 2018 Linaro Limited
595
+ * Written by Kevin Townsend <kevin.townsend@linaro.org>
128
+ * Written by Peter Maydell
596
+ *
129
+ *
597
+ * Based on: https://www.st.com/resource/en/datasheet/lsm303dlhc.pdf
130
+ * This program is free software; you can redistribute it and/or modify
598
+ *
131
+ * it under the terms of the GNU General Public License version 2 or
599
+ * SPDX-License-Identifier: GPL-2.0-or-later
132
+ * (at your option) any later version.
600
+ */
133
+ */
601
+
134
+
602
+#include "qemu/osdep.h"
135
+#include "qemu/osdep.h"
603
+#include "libqtest-single.h"
136
+#include "qemu/log.h"
604
+#include "libqos/qgraph.h"
137
+#include "qapi/error.h"
605
+#include "libqos/i2c.h"
138
+#include "trace.h"
606
+#include "qapi/qmp/qdict.h"
139
+#include "hw/sysbus.h"
607
+
140
+#include "hw/registerfields.h"
608
+#define LSM303DLHC_MAG_TEST_ID "lsm303dlhc_mag-test"
141
+#include "hw/misc/tz-mpc.h"
609
+#define LSM303DLHC_MAG_REG_CRA 0x00
142
+
610
+#define LSM303DLHC_MAG_REG_CRB 0x01
143
+/* Our IOMMU has two IOMMU indexes, one for secure transactions and one for
611
+#define LSM303DLHC_MAG_REG_OUT_X_H 0x03
144
+ * non-secure transactions.
612
+#define LSM303DLHC_MAG_REG_OUT_Z_H 0x05
145
+ */
613
+#define LSM303DLHC_MAG_REG_OUT_Y_H 0x07
146
+enum {
614
+#define LSM303DLHC_MAG_REG_IRC 0x0C
147
+ IOMMU_IDX_S,
615
+#define LSM303DLHC_MAG_REG_TEMP_OUT_H 0x31
148
+ IOMMU_IDX_NS,
616
+
149
+ IOMMU_NUM_INDEXES,
617
+static int qmp_lsm303dlhc_mag_get_property(const char *id, const char *prop)
150
+};
618
+{
151
+
619
+ QDict *response;
152
+/* Config registers */
620
+ int ret;
153
+REG32(CTRL, 0x00)
621
+
154
+REG32(BLK_MAX, 0x10)
622
+ response = qmp("{ 'execute': 'qom-get', 'arguments': { 'path': %s, "
155
+REG32(BLK_CFG, 0x14)
623
+ "'property': %s } }", id, prop);
156
+REG32(BLK_IDX, 0x18)
624
+ g_assert(qdict_haskey(response, "return"));
157
+REG32(BLK_LUT, 0x1c)
625
+ ret = qdict_get_int(response, "return");
158
+REG32(INT_STAT, 0x20)
626
+ qobject_unref(response);
159
+REG32(INT_CLEAR, 0x24)
160
+REG32(INT_EN, 0x28)
161
+REG32(INT_INFO1, 0x2c)
162
+REG32(INT_INFO2, 0x30)
163
+REG32(INT_SET, 0x34)
164
+REG32(PIDR4, 0xfd0)
165
+REG32(PIDR5, 0xfd4)
166
+REG32(PIDR6, 0xfd8)
167
+REG32(PIDR7, 0xfdc)
168
+REG32(PIDR0, 0xfe0)
169
+REG32(PIDR1, 0xfe4)
170
+REG32(PIDR2, 0xfe8)
171
+REG32(PIDR3, 0xfec)
172
+REG32(CIDR0, 0xff0)
173
+REG32(CIDR1, 0xff4)
174
+REG32(CIDR2, 0xff8)
175
+REG32(CIDR3, 0xffc)
176
+
177
+static const uint8_t tz_mpc_idregs[] = {
178
+ 0x04, 0x00, 0x00, 0x00,
179
+ 0x60, 0xb8, 0x1b, 0x00,
180
+ 0x0d, 0xf0, 0x05, 0xb1,
181
+};
182
+
183
+static MemTxResult tz_mpc_reg_read(void *opaque, hwaddr addr,
184
+ uint64_t *pdata,
185
+ unsigned size, MemTxAttrs attrs)
186
+{
187
+ uint64_t r;
188
+ uint32_t offset = addr & ~0x3;
189
+
190
+ if (!attrs.secure && offset < A_PIDR4) {
191
+ /* NS accesses can only see the ID registers */
192
+ qemu_log_mask(LOG_GUEST_ERROR,
193
+ "TZ MPC register read: NS access to offset 0x%x\n",
194
+ offset);
195
+ r = 0;
196
+ goto read_out;
197
+ }
198
+
199
+ switch (offset) {
200
+ case A_PIDR4:
201
+ case A_PIDR5:
202
+ case A_PIDR6:
203
+ case A_PIDR7:
204
+ case A_PIDR0:
205
+ case A_PIDR1:
206
+ case A_PIDR2:
207
+ case A_PIDR3:
208
+ case A_CIDR0:
209
+ case A_CIDR1:
210
+ case A_CIDR2:
211
+ case A_CIDR3:
212
+ r = tz_mpc_idregs[(offset - A_PIDR4) / 4];
213
+ break;
214
+ case A_INT_CLEAR:
215
+ case A_INT_SET:
216
+ qemu_log_mask(LOG_GUEST_ERROR,
217
+ "TZ MPC register read: write-only offset 0x%x\n",
218
+ offset);
219
+ r = 0;
220
+ break;
221
+ default:
222
+ qemu_log_mask(LOG_GUEST_ERROR,
223
+ "TZ MPC register read: bad offset 0x%x\n", offset);
224
+ r = 0;
225
+ break;
226
+ }
227
+
228
+ if (size != 4) {
229
+ /* None of our registers are read-sensitive (except BLK_LUT,
230
+ * which can special case the "size not 4" case), so just
231
+ * pull the right bytes out of the word read result.
232
+ */
233
+ r = extract32(r, (addr & 3) * 8, size * 8);
234
+ }
235
+
236
+read_out:
237
+ trace_tz_mpc_reg_read(addr, r, size);
238
+ *pdata = r;
239
+ return MEMTX_OK;
240
+}
241
+
242
+static MemTxResult tz_mpc_reg_write(void *opaque, hwaddr addr,
243
+ uint64_t value,
244
+ unsigned size, MemTxAttrs attrs)
245
+{
246
+ uint32_t offset = addr & ~0x3;
247
+
248
+ trace_tz_mpc_reg_write(addr, value, size);
249
+
250
+ if (!attrs.secure && offset < A_PIDR4) {
251
+ /* NS accesses can only see the ID registers */
252
+ qemu_log_mask(LOG_GUEST_ERROR,
253
+ "TZ MPC register write: NS access to offset 0x%x\n",
254
+ offset);
255
+ return MEMTX_OK;
256
+ }
257
+
258
+ if (size != 4) {
259
+ /* Expand the byte or halfword write to a full word size.
260
+ * In most cases we can do this with zeroes; the exceptions
261
+ * are CTRL, BLK_IDX and BLK_LUT.
262
+ */
263
+ uint32_t oldval;
264
+
265
+ switch (offset) {
266
+ /* As we add support for registers which need expansions
267
+ * other than zeroes we'll fill in cases here.
268
+ */
269
+ default:
270
+ oldval = 0;
271
+ break;
272
+ }
273
+ value = deposit32(oldval, (addr & 3) * 8, size * 8, value);
274
+ }
275
+
276
+ switch (offset) {
277
+ case A_PIDR4:
278
+ case A_PIDR5:
279
+ case A_PIDR6:
280
+ case A_PIDR7:
281
+ case A_PIDR0:
282
+ case A_PIDR1:
283
+ case A_PIDR2:
284
+ case A_PIDR3:
285
+ case A_CIDR0:
286
+ case A_CIDR1:
287
+ case A_CIDR2:
288
+ case A_CIDR3:
289
+ qemu_log_mask(LOG_GUEST_ERROR,
290
+ "TZ MPC register write: read-only offset 0x%x\n", offset);
291
+ break;
292
+ default:
293
+ qemu_log_mask(LOG_GUEST_ERROR,
294
+ "TZ MPC register write: bad offset 0x%x\n", offset);
295
+ break;
296
+ }
297
+
298
+ return MEMTX_OK;
299
+}
300
+
301
+static const MemoryRegionOps tz_mpc_reg_ops = {
302
+ .read_with_attrs = tz_mpc_reg_read,
303
+ .write_with_attrs = tz_mpc_reg_write,
304
+ .endianness = DEVICE_LITTLE_ENDIAN,
305
+ .valid.min_access_size = 1,
306
+ .valid.max_access_size = 4,
307
+ .impl.min_access_size = 1,
308
+ .impl.max_access_size = 4,
309
+};
310
+
311
+/* Accesses only reach these read and write functions if the MPC is
312
+ * blocking them; non-blocked accesses go directly to the downstream
313
+ * memory region without passing through this code.
314
+ */
315
+static MemTxResult tz_mpc_mem_blocked_read(void *opaque, hwaddr addr,
316
+ uint64_t *pdata,
317
+ unsigned size, MemTxAttrs attrs)
318
+{
319
+ trace_tz_mpc_mem_blocked_read(addr, size, attrs.secure);
320
+
321
+ *pdata = 0;
322
+ return MEMTX_OK;
323
+}
324
+
325
+static MemTxResult tz_mpc_mem_blocked_write(void *opaque, hwaddr addr,
326
+ uint64_t value,
327
+ unsigned size, MemTxAttrs attrs)
328
+{
329
+ trace_tz_mpc_mem_blocked_write(addr, value, size, attrs.secure);
330
+
331
+ return MEMTX_OK;
332
+}
333
+
334
+static const MemoryRegionOps tz_mpc_mem_blocked_ops = {
335
+ .read_with_attrs = tz_mpc_mem_blocked_read,
336
+ .write_with_attrs = tz_mpc_mem_blocked_write,
337
+ .endianness = DEVICE_LITTLE_ENDIAN,
338
+ .valid.min_access_size = 1,
339
+ .valid.max_access_size = 8,
340
+ .impl.min_access_size = 1,
341
+ .impl.max_access_size = 8,
342
+};
343
+
344
+static IOMMUTLBEntry tz_mpc_translate(IOMMUMemoryRegion *iommu,
345
+ hwaddr addr, IOMMUAccessFlags flags,
346
+ int iommu_idx)
347
+{
348
+ TZMPC *s = TZ_MPC(container_of(iommu, TZMPC, upstream));
349
+ bool ok;
350
+
351
+ IOMMUTLBEntry ret = {
352
+ .iova = addr & ~(s->blocksize - 1),
353
+ .translated_addr = addr & ~(s->blocksize - 1),
354
+ .addr_mask = s->blocksize - 1,
355
+ .perm = IOMMU_RW,
356
+ };
357
+
358
+ /* Look at the per-block configuration for this address, and
359
+ * return a TLB entry directing the transaction at either
360
+ * downstream_as or blocked_io_as, as appropriate.
361
+ * For the moment, always permit accesses.
362
+ */
363
+ ok = true;
364
+
365
+ trace_tz_mpc_translate(addr, flags,
366
+ iommu_idx == IOMMU_IDX_S ? "S" : "NS",
367
+ ok ? "pass" : "block");
368
+
369
+ ret.target_as = ok ? &s->downstream_as : &s->blocked_io_as;
627
+ return ret;
370
+ return ret;
628
+}
371
+}
629
+
372
+
630
+static void qmp_lsm303dlhc_mag_set_property(const char *id, const char *prop,
373
+static int tz_mpc_attrs_to_index(IOMMUMemoryRegion *iommu, MemTxAttrs attrs)
631
+ int value)
374
+{
632
+{
375
+ /* We treat unspecified attributes like secure. Transactions with
633
+ QDict *response;
376
+ * unspecified attributes come from places like
634
+
377
+ * cpu_physical_memory_write_rom() for initial image load, and we want
635
+ response = qmp("{ 'execute': 'qom-set', 'arguments': { 'path': %s, "
378
+ * those to pass through the from-reset "everything is secure" config.
636
+ "'property': %s, 'value': %d } }", id, prop, value);
379
+ * All the real during-emulation transactions from the CPU will
637
+ g_assert(qdict_haskey(response, "return"));
380
+ * specify attributes.
638
+ qobject_unref(response);
381
+ */
639
+}
382
+ return (attrs.unspecified || attrs.secure) ? IOMMU_IDX_S : IOMMU_IDX_NS;
640
+
383
+}
641
+static void send_and_receive(void *obj, void *data, QGuestAllocator *alloc)
384
+
642
+{
385
+static int tz_mpc_num_indexes(IOMMUMemoryRegion *iommu)
643
+ int64_t value;
386
+{
644
+ QI2CDevice *i2cdev = (QI2CDevice *)obj;
387
+ return IOMMU_NUM_INDEXES;
645
+
388
+}
646
+ /* Check default value for CRB */
389
+
647
+ g_assert_cmphex(i2c_get8(i2cdev, LSM303DLHC_MAG_REG_CRB), ==, 0x20);
390
+static void tz_mpc_reset(DeviceState *dev)
648
+
391
+{
649
+ /* Set x to 1.0 gauss and verify the value */
392
+}
650
+ qmp_lsm303dlhc_mag_set_property(LSM303DLHC_MAG_TEST_ID, "mag-x", 100000);
393
+
651
+ value = qmp_lsm303dlhc_mag_get_property(
394
+static void tz_mpc_init(Object *obj)
652
+ LSM303DLHC_MAG_TEST_ID, "mag-x");
395
+{
653
+ g_assert_cmpint(value, ==, 100000);
396
+ DeviceState *dev = DEVICE(obj);
654
+
397
+ TZMPC *s = TZ_MPC(obj);
655
+ /* Set y to 1.5 gauss and verify the value */
398
+
656
+ qmp_lsm303dlhc_mag_set_property(LSM303DLHC_MAG_TEST_ID, "mag-y", 150000);
399
+ qdev_init_gpio_out_named(dev, &s->irq, "irq", 1);
657
+ value = qmp_lsm303dlhc_mag_get_property(
400
+}
658
+ LSM303DLHC_MAG_TEST_ID, "mag-y");
401
+
659
+ g_assert_cmpint(value, ==, 150000);
402
+static void tz_mpc_realize(DeviceState *dev, Error **errp)
660
+
403
+{
661
+ /* Set z to 0.5 gauss and verify the value */
404
+ Object *obj = OBJECT(dev);
662
+ qmp_lsm303dlhc_mag_set_property(LSM303DLHC_MAG_TEST_ID, "mag-z", 50000);
405
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
663
+ value = qmp_lsm303dlhc_mag_get_property(
406
+ TZMPC *s = TZ_MPC(dev);
664
+ LSM303DLHC_MAG_TEST_ID, "mag-z");
407
+ uint64_t size;
665
+ g_assert_cmpint(value, ==, 50000);
408
+
666
+
409
+ /* We can't create the upstream end of the port until realize,
667
+ /* Set temperature to 23.6 C and verify the value */
410
+ * as we don't know the size of the MR used as the downstream until then.
668
+ qmp_lsm303dlhc_mag_set_property(LSM303DLHC_MAG_TEST_ID,
411
+ * We insist on having a downstream, to avoid complicating the code
669
+ "temperature", 23600);
412
+ * with handling the "don't know how big this is" case. It's easy
670
+ value = qmp_lsm303dlhc_mag_get_property(
413
+ * enough for the user to create an unimplemented_device as downstream
671
+ LSM303DLHC_MAG_TEST_ID, "temperature");
414
+ * if they have nothing else to plug into this.
672
+ /* Should return 23.5 C due to 0.125°C steps. */
415
+ */
673
+ g_assert_cmpint(value, ==, 23500);
416
+ if (!s->downstream) {
674
+
417
+ error_setg(errp, "MPC 'downstream' link not set");
675
+ /* Read raw x axis registers (1 gauss = 1100 at +/-1.3 g gain) */
418
+ return;
676
+ value = i2c_get16(i2cdev, LSM303DLHC_MAG_REG_OUT_X_H);
419
+ }
677
+ g_assert_cmphex(value, ==, 1100);
420
+
678
+
421
+ size = memory_region_size(s->downstream);
679
+ /* Read raw y axis registers (1.5 gauss = 1650 at +/- 1.3 g gain = ) */
422
+
680
+ value = i2c_get16(i2cdev, LSM303DLHC_MAG_REG_OUT_Y_H);
423
+ memory_region_init_iommu(&s->upstream, sizeof(s->upstream),
681
+ g_assert_cmphex(value, ==, 1650);
424
+ TYPE_TZ_MPC_IOMMU_MEMORY_REGION,
682
+
425
+ obj, "tz-mpc-upstream", size);
683
+ /* Read raw z axis registers (0.5 gauss = 490 at +/- 1.3 g gain = ) */
426
+
684
+ value = i2c_get16(i2cdev, LSM303DLHC_MAG_REG_OUT_Z_H);
427
+ /* In real hardware the block size is configurable. In QEMU we could
685
+ g_assert_cmphex(value, ==, 490);
428
+ * make it configurable but will need it to be at least as big as the
686
+
429
+ * target page size so we can execute out of the resulting MRs. Guest
687
+ /* Read raw temperature registers with temp disabled (CRA = 0x10) */
430
+ * software is supposed to check the block size using the BLK_CFG
688
+ value = i2c_get16(i2cdev, LSM303DLHC_MAG_REG_TEMP_OUT_H);
431
+ * register, so make it fixed at the page size.
689
+ g_assert_cmphex(value, ==, 0);
432
+ */
690
+
433
+ s->blocksize = memory_region_iommu_get_min_page_size(&s->upstream);
691
+ /* Enable temperature reads (CRA = 0x90) */
434
+ if (size % s->blocksize != 0) {
692
+ i2c_set8(i2cdev, LSM303DLHC_MAG_REG_CRA, 0x90);
435
+ error_setg(errp,
693
+
436
+ "MPC 'downstream' size %" PRId64
694
+ /* Read raw temp registers (23.5 C = 188 at 1 lsb = 0.125 C) */
437
+ " is not a multiple of %" HWADDR_PRIx " bytes",
695
+ value = i2c_get16(i2cdev, LSM303DLHC_MAG_REG_TEMP_OUT_H);
438
+ size, s->blocksize);
696
+ g_assert_cmphex(value, ==, 188);
439
+ object_unref(OBJECT(&s->upstream));
697
+}
440
+ return;
698
+
441
+ }
699
+static void reg_wraparound(void *obj, void *data, QGuestAllocator *alloc)
442
+
700
+{
443
+ /* BLK_MAX is the max value of BLK_IDX, which indexes an array of 32-bit
701
+ uint8_t value[4];
444
+ * words, each bit of which indicates one block.
702
+ QI2CDevice *i2cdev = (QI2CDevice *)obj;
445
+ */
703
+
446
+ s->blk_max = DIV_ROUND_UP(size / s->blocksize, 32);
704
+ /* Set x to 1.0 gauss, and y to 1.5 gauss for known test values */
447
+
705
+ qmp_lsm303dlhc_mag_set_property(LSM303DLHC_MAG_TEST_ID, "mag-x", 100000);
448
+ memory_region_init_io(&s->regmr, obj, &tz_mpc_reg_ops,
706
+ qmp_lsm303dlhc_mag_set_property(LSM303DLHC_MAG_TEST_ID, "mag-y", 150000);
449
+ s, "tz-mpc-regs", 0x1000);
707
+
450
+ sysbus_init_mmio(sbd, &s->regmr);
708
+ /* Check that requesting 4 bytes starting at Y_H wraps around to X_L */
451
+
709
+ i2c_read_block(i2cdev, LSM303DLHC_MAG_REG_OUT_Y_H, value, 4);
452
+ sysbus_init_mmio(sbd, MEMORY_REGION(&s->upstream));
710
+ /* 1.5 gauss = 1650 lsb = 0x672 */
453
+
711
+ g_assert_cmphex(value[0], ==, 0x06);
454
+ /* This memory region is not exposed to users of this device as a
712
+ g_assert_cmphex(value[1], ==, 0x72);
455
+ * sysbus MMIO region, but is instead used internally as something
713
+ /* 1.0 gauss = 1100 lsb = 0x44C */
456
+ * that our IOMMU translate function might direct accesses to.
714
+ g_assert_cmphex(value[2], ==, 0x04);
457
+ */
715
+ g_assert_cmphex(value[3], ==, 0x4C);
458
+ memory_region_init_io(&s->blocked_io, obj, &tz_mpc_mem_blocked_ops,
716
+
459
+ s, "tz-mpc-blocked-io", size);
717
+ /* Check that requesting LSM303DLHC_MAG_REG_IRC wraps around to CRA */
460
+
718
+ i2c_read_block(i2cdev, LSM303DLHC_MAG_REG_IRC, value, 2);
461
+ address_space_init(&s->downstream_as, s->downstream,
719
+ /* Default value for IRC = 0x33 */
462
+ "tz-mpc-downstream");
720
+ g_assert_cmphex(value[0], ==, 0x33);
463
+ address_space_init(&s->blocked_io_as, &s->blocked_io,
721
+ /* Default value for CRA = 0x10 */
464
+ "tz-mpc-blocked-io");
722
+ g_assert_cmphex(value[1], ==, 0x10);
465
+}
723
+}
466
+
724
+
467
+static const VMStateDescription tz_mpc_vmstate = {
725
+static void lsm303dlhc_mag_register_nodes(void)
468
+ .name = "tz-mpc",
726
+{
469
+ .version_id = 1,
727
+ QOSGraphEdgeOptions opts = {
470
+ .minimum_version_id = 1,
728
+ .extra_device_opts = "id=" LSM303DLHC_MAG_TEST_ID ",address=0x1e"
471
+ .fields = (VMStateField[]) {
729
+ };
472
+ VMSTATE_END_OF_LIST()
730
+ add_qi2c_address(&opts, &(QI2CAddress) { 0x1E });
473
+ }
731
+
474
+};
732
+ qos_node_create_driver("lsm303dlhc_mag", i2c_device_create);
475
+
733
+ qos_node_consumes("lsm303dlhc_mag", "i2c-bus", &opts);
476
+static Property tz_mpc_properties[] = {
734
+
477
+ DEFINE_PROP_LINK("downstream", TZMPC, downstream,
735
+ qos_add_test("tx-rx", "lsm303dlhc_mag", send_and_receive, NULL);
478
+ TYPE_MEMORY_REGION, MemoryRegion *),
736
+ qos_add_test("regwrap", "lsm303dlhc_mag", reg_wraparound, NULL);
479
+ DEFINE_PROP_END_OF_LIST(),
737
+}
480
+};
738
+libqos_init(lsm303dlhc_mag_register_nodes);
481
+
739
diff --git a/hw/sensor/Kconfig b/hw/sensor/Kconfig
482
+static void tz_mpc_class_init(ObjectClass *klass, void *data)
483
+{
484
+ DeviceClass *dc = DEVICE_CLASS(klass);
485
+
486
+ dc->realize = tz_mpc_realize;
487
+ dc->vmsd = &tz_mpc_vmstate;
488
+ dc->reset = tz_mpc_reset;
489
+ dc->props = tz_mpc_properties;
490
+}
491
+
492
+static const TypeInfo tz_mpc_info = {
493
+ .name = TYPE_TZ_MPC,
494
+ .parent = TYPE_SYS_BUS_DEVICE,
495
+ .instance_size = sizeof(TZMPC),
496
+ .instance_init = tz_mpc_init,
497
+ .class_init = tz_mpc_class_init,
498
+};
499
+
500
+static void tz_mpc_iommu_memory_region_class_init(ObjectClass *klass,
501
+ void *data)
502
+{
503
+ IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
504
+
505
+ imrc->translate = tz_mpc_translate;
506
+ imrc->attrs_to_index = tz_mpc_attrs_to_index;
507
+ imrc->num_indexes = tz_mpc_num_indexes;
508
+}
509
+
510
+static const TypeInfo tz_mpc_iommu_memory_region_info = {
511
+ .name = TYPE_TZ_MPC_IOMMU_MEMORY_REGION,
512
+ .parent = TYPE_IOMMU_MEMORY_REGION,
513
+ .class_init = tz_mpc_iommu_memory_region_class_init,
514
+};
515
+
516
+static void tz_mpc_register_types(void)
517
+{
518
+ type_register_static(&tz_mpc_info);
519
+ type_register_static(&tz_mpc_iommu_memory_region_info);
520
+}
521
+
522
+type_init(tz_mpc_register_types);
523
diff --git a/MAINTAINERS b/MAINTAINERS
740
index XXXXXXX..XXXXXXX 100644
524
index XXXXXXX..XXXXXXX 100644
741
--- a/hw/sensor/Kconfig
525
--- a/MAINTAINERS
742
+++ b/hw/sensor/Kconfig
526
+++ b/MAINTAINERS
743
@@ -XXX,XX +XXX,XX @@ config ADM1272
527
@@ -XXX,XX +XXX,XX @@ F: hw/char/cmsdk-apb-uart.c
744
config MAX34451
528
F: include/hw/char/cmsdk-apb-uart.h
745
bool
529
F: hw/misc/tz-ppc.c
746
depends on I2C
530
F: include/hw/misc/tz-ppc.h
747
+
531
+F: hw/misc/tz-mpc.c
748
+config LSM303DLHC_MAG
532
+F: include/hw/misc/tz-mpc.h
749
+ bool
533
750
+ depends on I2C
534
ARM cores
751
diff --git a/hw/sensor/meson.build b/hw/sensor/meson.build
535
M: Peter Maydell <peter.maydell@linaro.org>
536
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
752
index XXXXXXX..XXXXXXX 100644
537
index XXXXXXX..XXXXXXX 100644
753
--- a/hw/sensor/meson.build
538
--- a/default-configs/arm-softmmu.mak
754
+++ b/hw/sensor/meson.build
539
+++ b/default-configs/arm-softmmu.mak
755
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_DPS310', if_true: files('dps310.c'))
540
@@ -XXX,XX +XXX,XX @@ CONFIG_CMSDK_APB_UART=y
756
softmmu_ss.add(when: 'CONFIG_EMC141X', if_true: files('emc141x.c'))
541
CONFIG_MPS2_FPGAIO=y
757
softmmu_ss.add(when: 'CONFIG_ADM1272', if_true: files('adm1272.c'))
542
CONFIG_MPS2_SCC=y
758
softmmu_ss.add(when: 'CONFIG_MAX34451', if_true: files('max34451.c'))
543
759
+softmmu_ss.add(when: 'CONFIG_LSM303DLHC_MAG', if_true: files('lsm303dlhc_mag.c'))
544
+CONFIG_TZ_MPC=y
760
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
545
CONFIG_TZ_PPC=y
546
CONFIG_IOTKIT=y
547
CONFIG_IOTKIT_SECCTL=y
548
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
761
index XXXXXXX..XXXXXXX 100644
549
index XXXXXXX..XXXXXXX 100644
762
--- a/tests/qtest/meson.build
550
--- a/hw/misc/trace-events
763
+++ b/tests/qtest/meson.build
551
+++ b/hw/misc/trace-events
764
@@ -XXX,XX +XXX,XX @@ qos_test_ss.add(
552
@@ -XXX,XX +XXX,XX @@ mos6522_set_sr_int(void) "set sr_int"
765
'eepro100-test.c',
553
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
766
'es1370-test.c',
554
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
767
'ipoctal232-test.c',
555
768
+ 'lsm303dlhc-mag-test.c',
556
+# hw/misc/tz-mpc.c
769
'max34451-test.c',
557
+tz_mpc_reg_read(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs read: offset 0x%x data 0x%" PRIx64 " size %u"
770
'megasas-test.c',
558
+tz_mpc_reg_write(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs write: offset 0x%x data 0x%" PRIx64 " size %u"
771
'ne2000-test.c',
559
+tz_mpc_mem_blocked_read(uint64_t addr, unsigned size, bool secure) "TZ MPC blocked read: offset 0x%" PRIx64 " size %u secure %d"
560
+tz_mpc_mem_blocked_write(uint64_t addr, uint64_t data, unsigned size, bool secure) "TZ MPC blocked write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
561
+tz_mpc_translate(uint64_t addr, int flags, const char *idx, const char *res) "TZ MPC translate: addr 0x%" PRIx64 " flags 0x%x iommu_idx %s: %s"
562
+
563
# hw/misc/tz-ppc.c
564
tz_ppc_reset(void) "TZ PPC: reset"
565
tz_ppc_cfg_nonsec(int n, int level) "TZ PPC: cfg_nonsec[%d] = %d"
772
--
566
--
773
2.25.1
567
2.17.1
774
568
775
569
diff view generated by jsdifflib
1
The CPU object's start-powered-off property is currently only
1
Implement the missing registers for the TZ MPC.
2
settable before the CPU object is realized. For arm machines this is
3
awkward, because we would like to decide whether the CPU should be
4
powered-off based on how we are booting the guest code, which is
5
something done in the machine model code and in common code called by
6
the machine model, which runs much later and in completely different
7
parts of the codebase from the SoC object code that is responsible
8
for creating and realizing the CPU objects.
9
10
Allow start-powered-off to be set after realize. Since this isn't
11
something that's supported by the DEFINE_PROP_* macros, we have to
12
switch the property definition to use the
13
object_class_property_add_bool() function.
14
15
Note that it doesn't conceptually make sense to change the setting of
16
the property after the machine has been completely initialized,
17
beacuse this would mean that the behaviour of the machine when first
18
started would differ from its behaviour when the system is
19
subsequently reset. (It would also require the underlying state to
20
be migrated, which we don't do.)
21
2
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Eric Auger <eric.auger@redhat.com>
24
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
5
Message-id: 20180620132032.28865-3-peter.maydell@linaro.org
25
Tested-by: Cédric Le Goater <clg@kaod.org>
26
Message-id: 20220127154639.2090164-3-peter.maydell@linaro.org
27
---
6
---
28
cpu.c | 22 +++++++++++++++++++++-
7
include/hw/misc/tz-mpc.h | 10 +++
29
1 file changed, 21 insertions(+), 1 deletion(-)
8
hw/misc/tz-mpc.c | 140 ++++++++++++++++++++++++++++++++++++++-
30
9
2 files changed, 147 insertions(+), 3 deletions(-)
31
diff --git a/cpu.c b/cpu.c
10
11
diff --git a/include/hw/misc/tz-mpc.h b/include/hw/misc/tz-mpc.h
32
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
33
--- a/cpu.c
13
--- a/include/hw/misc/tz-mpc.h
34
+++ b/cpu.c
14
+++ b/include/hw/misc/tz-mpc.h
35
@@ -XXX,XX +XXX,XX @@ static Property cpu_common_props[] = {
15
@@ -XXX,XX +XXX,XX @@ struct TZMPC {
36
DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION,
16
37
MemoryRegion *),
17
/*< public >*/
38
#endif
18
39
- DEFINE_PROP_BOOL("start-powered-off", CPUState, start_powered_off, false),
19
+ /* State */
40
DEFINE_PROP_END_OF_LIST(),
20
+ uint32_t ctrl;
21
+ uint32_t blk_idx;
22
+ uint32_t int_stat;
23
+ uint32_t int_en;
24
+ uint32_t int_info1;
25
+ uint32_t int_info2;
26
+
27
+ uint32_t *blk_lut;
28
+
29
qemu_irq irq;
30
31
/* Properties */
32
diff --git a/hw/misc/tz-mpc.c b/hw/misc/tz-mpc.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/misc/tz-mpc.c
35
+++ b/hw/misc/tz-mpc.c
36
@@ -XXX,XX +XXX,XX @@ enum {
37
38
/* Config registers */
39
REG32(CTRL, 0x00)
40
+ FIELD(CTRL, SEC_RESP, 4, 1)
41
+ FIELD(CTRL, AUTOINC, 8, 1)
42
+ FIELD(CTRL, LOCKDOWN, 31, 1)
43
REG32(BLK_MAX, 0x10)
44
REG32(BLK_CFG, 0x14)
45
REG32(BLK_IDX, 0x18)
46
REG32(BLK_LUT, 0x1c)
47
REG32(INT_STAT, 0x20)
48
+ FIELD(INT_STAT, IRQ, 0, 1)
49
REG32(INT_CLEAR, 0x24)
50
+ FIELD(INT_CLEAR, IRQ, 0, 1)
51
REG32(INT_EN, 0x28)
52
+ FIELD(INT_EN, IRQ, 0, 1)
53
REG32(INT_INFO1, 0x2c)
54
REG32(INT_INFO2, 0x30)
55
REG32(INT_SET, 0x34)
56
+ FIELD(INT_SET, IRQ, 0, 1)
57
REG32(PIDR4, 0xfd0)
58
REG32(PIDR5, 0xfd4)
59
REG32(PIDR6, 0xfd8)
60
@@ -XXX,XX +XXX,XX @@ static const uint8_t tz_mpc_idregs[] = {
61
0x0d, 0xf0, 0x05, 0xb1,
41
};
62
};
42
63
43
+static bool cpu_get_start_powered_off(Object *obj, Error **errp)
64
+static void tz_mpc_irq_update(TZMPC *s)
44
+{
65
+{
45
+ CPUState *cpu = CPU(obj);
66
+ qemu_set_irq(s->irq, s->int_stat && s->int_en);
46
+ return cpu->start_powered_off;
47
+}
67
+}
48
+
68
+
49
+static void cpu_set_start_powered_off(Object *obj, bool value, Error **errp)
69
+static void tz_mpc_autoinc_idx(TZMPC *s, unsigned access_size)
50
+{
70
+{
51
+ CPUState *cpu = CPU(obj);
71
+ /* Auto-increment BLK_IDX if necessary */
52
+ cpu->start_powered_off = value;
72
+ if (access_size == 4 && (s->ctrl & R_CTRL_AUTOINC_MASK)) {
73
+ s->blk_idx++;
74
+ s->blk_idx %= s->blk_max;
75
+ }
53
+}
76
+}
54
+
77
+
55
void cpu_class_init_props(DeviceClass *dc)
78
static MemTxResult tz_mpc_reg_read(void *opaque, hwaddr addr,
79
uint64_t *pdata,
80
unsigned size, MemTxAttrs attrs)
56
{
81
{
57
+ ObjectClass *oc = OBJECT_CLASS(dc);
82
+ TZMPC *s = TZ_MPC(opaque);
58
+
83
uint64_t r;
59
device_class_set_props(dc, cpu_common_props);
84
uint32_t offset = addr & ~0x3;
60
+ /*
85
61
+ * We can't use DEFINE_PROP_BOOL in the Property array for this
86
@@ -XXX,XX +XXX,XX @@ static MemTxResult tz_mpc_reg_read(void *opaque, hwaddr addr,
62
+ * property, because we want this to be settable after realize.
87
}
63
+ */
88
64
+ object_class_property_add_bool(oc, "start-powered-off",
89
switch (offset) {
65
+ cpu_get_start_powered_off,
90
+ case A_CTRL:
66
+ cpu_set_start_powered_off);
91
+ r = s->ctrl;
92
+ break;
93
+ case A_BLK_MAX:
94
+ r = s->blk_max;
95
+ break;
96
+ case A_BLK_CFG:
97
+ /* We are never in "init in progress state", so this just indicates
98
+ * the block size. s->blocksize == (1 << BLK_CFG + 5), so
99
+ * BLK_CFG == ctz32(s->blocksize) - 5
100
+ */
101
+ r = ctz32(s->blocksize) - 5;
102
+ break;
103
+ case A_BLK_IDX:
104
+ r = s->blk_idx;
105
+ break;
106
+ case A_BLK_LUT:
107
+ r = s->blk_lut[s->blk_idx];
108
+ tz_mpc_autoinc_idx(s, size);
109
+ break;
110
+ case A_INT_STAT:
111
+ r = s->int_stat;
112
+ break;
113
+ case A_INT_EN:
114
+ r = s->int_en;
115
+ break;
116
+ case A_INT_INFO1:
117
+ r = s->int_info1;
118
+ break;
119
+ case A_INT_INFO2:
120
+ r = s->int_info2;
121
+ break;
122
case A_PIDR4:
123
case A_PIDR5:
124
case A_PIDR6:
125
@@ -XXX,XX +XXX,XX @@ static MemTxResult tz_mpc_reg_write(void *opaque, hwaddr addr,
126
uint64_t value,
127
unsigned size, MemTxAttrs attrs)
128
{
129
+ TZMPC *s = TZ_MPC(opaque);
130
uint32_t offset = addr & ~0x3;
131
132
trace_tz_mpc_reg_write(addr, value, size);
133
@@ -XXX,XX +XXX,XX @@ static MemTxResult tz_mpc_reg_write(void *opaque, hwaddr addr,
134
uint32_t oldval;
135
136
switch (offset) {
137
- /* As we add support for registers which need expansions
138
- * other than zeroes we'll fill in cases here.
139
- */
140
+ case A_CTRL:
141
+ oldval = s->ctrl;
142
+ break;
143
+ case A_BLK_IDX:
144
+ oldval = s->blk_idx;
145
+ break;
146
+ case A_BLK_LUT:
147
+ oldval = s->blk_lut[s->blk_idx];
148
+ break;
149
default:
150
oldval = 0;
151
break;
152
@@ -XXX,XX +XXX,XX @@ static MemTxResult tz_mpc_reg_write(void *opaque, hwaddr addr,
153
value = deposit32(oldval, (addr & 3) * 8, size * 8, value);
154
}
155
156
+ if ((s->ctrl & R_CTRL_LOCKDOWN_MASK) &&
157
+ (offset == A_CTRL || offset == A_BLK_LUT || offset == A_INT_EN)) {
158
+ /* Lockdown mode makes these three registers read-only, and
159
+ * the only way out of it is to reset the device.
160
+ */
161
+ qemu_log_mask(LOG_GUEST_ERROR, "TZ MPC register write to offset 0x%x "
162
+ "while MPC is in lockdown mode\n", offset);
163
+ return MEMTX_OK;
164
+ }
165
+
166
switch (offset) {
167
+ case A_CTRL:
168
+ /* We don't implement the 'data gating' feature so all other bits
169
+ * are reserved and we make them RAZ/WI.
170
+ */
171
+ s->ctrl = value & (R_CTRL_SEC_RESP_MASK |
172
+ R_CTRL_AUTOINC_MASK |
173
+ R_CTRL_LOCKDOWN_MASK);
174
+ break;
175
+ case A_BLK_IDX:
176
+ s->blk_idx = value % s->blk_max;
177
+ break;
178
+ case A_BLK_LUT:
179
+ s->blk_lut[s->blk_idx] = value;
180
+ tz_mpc_autoinc_idx(s, size);
181
+ break;
182
+ case A_INT_CLEAR:
183
+ if (value & R_INT_CLEAR_IRQ_MASK) {
184
+ s->int_stat = 0;
185
+ tz_mpc_irq_update(s);
186
+ }
187
+ break;
188
+ case A_INT_EN:
189
+ s->int_en = value & R_INT_EN_IRQ_MASK;
190
+ tz_mpc_irq_update(s);
191
+ break;
192
+ case A_INT_SET:
193
+ if (value & R_INT_SET_IRQ_MASK) {
194
+ s->int_stat = R_INT_STAT_IRQ_MASK;
195
+ tz_mpc_irq_update(s);
196
+ }
197
+ break;
198
case A_PIDR4:
199
case A_PIDR5:
200
case A_PIDR6:
201
@@ -XXX,XX +XXX,XX @@ static int tz_mpc_num_indexes(IOMMUMemoryRegion *iommu)
202
203
static void tz_mpc_reset(DeviceState *dev)
204
{
205
+ TZMPC *s = TZ_MPC(dev);
206
+
207
+ s->ctrl = 0x00000100;
208
+ s->blk_idx = 0;
209
+ s->int_stat = 0;
210
+ s->int_en = 1;
211
+ s->int_info1 = 0;
212
+ s->int_info2 = 0;
213
+
214
+ memset(s->blk_lut, 0, s->blk_max * sizeof(uint32_t));
67
}
215
}
68
216
69
void cpu_exec_initfn(CPUState *cpu)
217
static void tz_mpc_init(Object *obj)
218
@@ -XXX,XX +XXX,XX @@ static void tz_mpc_realize(DeviceState *dev, Error **errp)
219
"tz-mpc-downstream");
220
address_space_init(&s->blocked_io_as, &s->blocked_io,
221
"tz-mpc-blocked-io");
222
+
223
+ s->blk_lut = g_new(uint32_t, s->blk_max);
224
+}
225
+
226
+static int tz_mpc_post_load(void *opaque, int version_id)
227
+{
228
+ TZMPC *s = TZ_MPC(opaque);
229
+
230
+ /* Check the incoming data doesn't point blk_idx off the end of blk_lut. */
231
+ if (s->blk_idx >= s->blk_max) {
232
+ return -1;
233
+ }
234
+ return 0;
235
}
236
237
static const VMStateDescription tz_mpc_vmstate = {
238
.name = "tz-mpc",
239
.version_id = 1,
240
.minimum_version_id = 1,
241
+ .post_load = tz_mpc_post_load,
242
.fields = (VMStateField[]) {
243
+ VMSTATE_UINT32(ctrl, TZMPC),
244
+ VMSTATE_UINT32(blk_idx, TZMPC),
245
+ VMSTATE_UINT32(int_stat, TZMPC),
246
+ VMSTATE_UINT32(int_en, TZMPC),
247
+ VMSTATE_UINT32(int_info1, TZMPC),
248
+ VMSTATE_UINT32(int_info2, TZMPC),
249
+ VMSTATE_VARRAY_UINT32(blk_lut, TZMPC, blk_max,
250
+ 0, vmstate_info_uint32, uint32_t),
251
VMSTATE_END_OF_LIST()
252
}
253
};
70
--
254
--
71
2.25.1
255
2.17.1
72
256
73
257
diff view generated by jsdifflib
1
Currently the ITS accesses each 8-byte doubleword in a 4-doubleword
1
The MPC is guest-configurable for whether blocked accesses:
2
command packet with a separate address_space_ldq_le() call. This is
2
* should be RAZ/WI or cause a bus error
3
awkward because the individual command processing functions have
3
* should generate an interrupt or not
4
ended up with code to handle "load more doublewords out of the
5
packet", which is both unwieldy and also a potential source of bugs
6
because it's not obvious when looking at a line that pulls a field
7
out of the 'value' variable which of the 4 doublewords that variable
8
currently holds.
9
4
10
Switch to using address_space_map() to map the whole command packet
5
Implement this behaviour in the blocked-access handlers.
11
at once and fish the four doublewords out of it. Then each process_*
12
function can start with a few lines of code that extract the fields
13
it cares about.
14
15
This requires us to split out the guts of process_its_cmd() into a
16
new do_process_its_cmd(), because we were previously overloading the
17
value and offset arguments as a backdoor way to directly pass the
18
devid and eventid from a write to GITS_TRANSLATER. The new
19
do_process_its_cmd() takes those arguments directly, and
20
process_its_cmd() is just a wrapper that does the "read fields from
21
command packet" part.
22
6
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Eric Auger <eric.auger@redhat.com>
25
Message-id: 20220201193207.2771604-2-peter.maydell@linaro.org
9
Message-id: 20180620132032.28865-4-peter.maydell@linaro.org
26
---
10
---
27
hw/intc/gicv3_internal.h | 4 +-
11
hw/misc/tz-mpc.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++--
28
hw/intc/arm_gicv3_its.c | 208 +++++++++++----------------------------
12
1 file changed, 48 insertions(+), 2 deletions(-)
29
2 files changed, 62 insertions(+), 150 deletions(-)
30
13
31
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
14
diff --git a/hw/misc/tz-mpc.c b/hw/misc/tz-mpc.c
32
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/intc/gicv3_internal.h
16
--- a/hw/misc/tz-mpc.c
34
+++ b/hw/intc/gicv3_internal.h
17
+++ b/hw/misc/tz-mpc.c
35
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
18
@@ -XXX,XX +XXX,XX @@ REG32(INT_EN, 0x28)
36
#define LPI_CTE_ENABLED TABLE_ENTRY_VALID_MASK
19
FIELD(INT_EN, IRQ, 0, 1)
37
#define LPI_PRIORITY_MASK 0xfc
20
REG32(INT_INFO1, 0x2c)
38
21
REG32(INT_INFO2, 0x30)
39
-#define GITS_CMDQ_ENTRY_SIZE 32
22
+ FIELD(INT_INFO2, HMASTER, 0, 16)
40
-#define NUM_BYTES_IN_DW 8
23
+ FIELD(INT_INFO2, HNONSEC, 16, 1)
41
+#define GITS_CMDQ_ENTRY_WORDS 4
24
+ FIELD(INT_INFO2, CFG_NS, 17, 1)
42
+#define GITS_CMDQ_ENTRY_SIZE (GITS_CMDQ_ENTRY_WORDS * sizeof(uint64_t))
25
REG32(INT_SET, 0x34)
43
26
FIELD(INT_SET, IRQ, 0, 1)
44
#define CMD_MASK 0xff
27
REG32(PIDR4, 0xfd0)
45
28
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps tz_mpc_reg_ops = {
46
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
29
.impl.max_access_size = 4,
47
index XXXXXXX..XXXXXXX 100644
30
};
48
--- a/hw/intc/arm_gicv3_its.c
31
49
+++ b/hw/intc/arm_gicv3_its.c
32
+static inline bool tz_mpc_cfg_ns(TZMPC *s, hwaddr addr)
50
@@ -XXX,XX +XXX,XX @@ static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
51
* 3. handling of ITS CLEAR command
52
* 4. handling of ITS DISCARD command
53
*/
54
-static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
55
- uint32_t offset, ItsCmdType cmd)
56
+static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
57
+ uint32_t eventid, ItsCmdType cmd)
58
{
59
- AddressSpace *as = &s->gicv3->dma_as;
60
- uint32_t devid, eventid;
61
MemTxResult res = MEMTX_OK;
62
bool dte_valid;
63
uint64_t dte = 0;
64
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
65
bool cte_valid = false;
66
uint64_t rdbase;
67
68
- if (cmd == NONE) {
69
- devid = offset;
70
- } else {
71
- devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
72
-
73
- offset += NUM_BYTES_IN_DW;
74
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
75
- MEMTXATTRS_UNSPECIFIED, &res);
76
- }
77
-
78
- if (res != MEMTX_OK) {
79
- return CMD_STALL;
80
- }
81
-
82
- eventid = (value & EVENTID_MASK);
83
-
84
if (devid >= s->dt.num_entries) {
85
qemu_log_mask(LOG_GUEST_ERROR,
86
"%s: invalid command attributes: devid %d>=%d",
87
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
88
}
89
return CMD_CONTINUE;
90
}
91
-
92
-static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value,
93
- uint32_t offset, bool ignore_pInt)
94
+static ItsCmdResult process_its_cmd(GICv3ITSState *s, const uint64_t *cmdpkt,
95
+ ItsCmdType cmd)
96
+{
33
+{
97
+ uint32_t devid, eventid;
34
+ /* Return the cfg_ns bit from the LUT for the specified address */
35
+ hwaddr blknum = addr / s->blocksize;
36
+ hwaddr blkword = blknum / 32;
37
+ uint32_t blkbit = 1U << (blknum % 32);
98
+
38
+
99
+ devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
39
+ /* This would imply the address was larger than the size we
100
+ eventid = cmdpkt[1] & EVENTID_MASK;
40
+ * defined this memory region to be, so it can't happen.
101
+ return do_process_its_cmd(s, devid, eventid, cmd);
41
+ */
42
+ assert(blkword < s->blk_max);
43
+ return s->blk_lut[blkword] & blkbit;
102
+}
44
+}
103
+
45
+
104
+static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
46
+static MemTxResult tz_mpc_handle_block(TZMPC *s, hwaddr addr, MemTxAttrs attrs)
105
+ bool ignore_pInt)
47
+{
48
+ /* Handle a blocked transaction: raise IRQ, capture info, etc */
49
+ if (!s->int_stat) {
50
+ /* First blocked transfer: capture information into INT_INFO1 and
51
+ * INT_INFO2. Subsequent transfers are still blocked but don't
52
+ * capture information until the guest clears the interrupt.
53
+ */
54
+
55
+ s->int_info1 = addr;
56
+ s->int_info2 = 0;
57
+ s->int_info2 = FIELD_DP32(s->int_info2, INT_INFO2, HMASTER,
58
+ attrs.requester_id & 0xffff);
59
+ s->int_info2 = FIELD_DP32(s->int_info2, INT_INFO2, HNONSEC,
60
+ ~attrs.secure);
61
+ s->int_info2 = FIELD_DP32(s->int_info2, INT_INFO2, CFG_NS,
62
+ tz_mpc_cfg_ns(s, addr));
63
+ s->int_stat |= R_INT_STAT_IRQ_MASK;
64
+ tz_mpc_irq_update(s);
65
+ }
66
+
67
+ /* Generate bus error if desired; otherwise RAZ/WI */
68
+ return (s->ctrl & R_CTRL_SEC_RESP_MASK) ? MEMTX_ERROR : MEMTX_OK;
69
+}
70
+
71
/* Accesses only reach these read and write functions if the MPC is
72
* blocking them; non-blocked accesses go directly to the downstream
73
* memory region without passing through this code.
74
@@ -XXX,XX +XXX,XX @@ static MemTxResult tz_mpc_mem_blocked_read(void *opaque, hwaddr addr,
75
uint64_t *pdata,
76
unsigned size, MemTxAttrs attrs)
106
{
77
{
107
- AddressSpace *as = &s->gicv3->dma_as;
78
+ TZMPC *s = TZ_MPC(opaque);
108
uint32_t devid, eventid;
79
+
109
uint32_t pIntid = 0;
80
trace_tz_mpc_mem_blocked_read(addr, size, attrs.secure);
110
uint64_t num_eventids;
81
111
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value,
82
*pdata = 0;
112
uint64_t dte = 0;
83
- return MEMTX_OK;
113
IteEntry ite = {};
84
+ return tz_mpc_handle_block(s, addr, attrs);
114
115
- devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
116
- offset += NUM_BYTES_IN_DW;
117
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
118
- MEMTXATTRS_UNSPECIFIED, &res);
119
-
120
- if (res != MEMTX_OK) {
121
- return CMD_STALL;
122
- }
123
-
124
- eventid = (value & EVENTID_MASK);
125
+ devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
126
+ eventid = cmdpkt[1] & EVENTID_MASK;
127
128
if (ignore_pInt) {
129
pIntid = eventid;
130
} else {
131
- pIntid = ((value & pINTID_MASK) >> pINTID_SHIFT);
132
+ pIntid = (cmdpkt[1] & pINTID_MASK) >> pINTID_SHIFT;
133
}
134
135
- offset += NUM_BYTES_IN_DW;
136
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
137
- MEMTXATTRS_UNSPECIFIED, &res);
138
-
139
- if (res != MEMTX_OK) {
140
- return CMD_STALL;
141
- }
142
-
143
- icid = value & ICID_MASK;
144
+ icid = cmdpkt[2] & ICID_MASK;
145
146
if (devid >= s->dt.num_entries) {
147
qemu_log_mask(LOG_GUEST_ERROR,
148
@@ -XXX,XX +XXX,XX @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
149
return res == MEMTX_OK;
150
}
85
}
151
86
152
-static ItsCmdResult process_mapc(GICv3ITSState *s, uint32_t offset)
87
static MemTxResult tz_mpc_mem_blocked_write(void *opaque, hwaddr addr,
153
+static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt)
88
uint64_t value,
89
unsigned size, MemTxAttrs attrs)
154
{
90
{
155
- AddressSpace *as = &s->gicv3->dma_as;
91
+ TZMPC *s = TZ_MPC(opaque);
156
uint16_t icid;
92
+
157
uint64_t rdbase;
93
trace_tz_mpc_mem_blocked_write(addr, value, size, attrs.secure);
158
bool valid;
94
159
- MemTxResult res = MEMTX_OK;
95
- return MEMTX_OK;
160
- uint64_t value;
96
+ return tz_mpc_handle_block(s, addr, attrs);
161
162
- offset += NUM_BYTES_IN_DW;
163
- offset += NUM_BYTES_IN_DW;
164
+ icid = cmdpkt[2] & ICID_MASK;
165
166
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
167
- MEMTXATTRS_UNSPECIFIED, &res);
168
-
169
- if (res != MEMTX_OK) {
170
- return CMD_STALL;
171
- }
172
-
173
- icid = value & ICID_MASK;
174
-
175
- rdbase = (value & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
176
+ rdbase = (cmdpkt[2] & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
177
rdbase &= RDBASE_PROCNUM_MASK;
178
179
- valid = (value & CMD_FIELD_VALID_MASK);
180
+ valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
181
182
if ((icid >= s->ct.num_entries) || (rdbase >= s->gicv3->num_cpu)) {
183
qemu_log_mask(LOG_GUEST_ERROR,
184
@@ -XXX,XX +XXX,XX @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
185
return res == MEMTX_OK;
186
}
97
}
187
98
188
-static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value,
99
static const MemoryRegionOps tz_mpc_mem_blocked_ops = {
189
- uint32_t offset)
190
+static ItsCmdResult process_mapd(GICv3ITSState *s, const uint64_t *cmdpkt)
191
{
192
- AddressSpace *as = &s->gicv3->dma_as;
193
uint32_t devid;
194
uint8_t size;
195
uint64_t itt_addr;
196
bool valid;
197
- MemTxResult res = MEMTX_OK;
198
199
- devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
200
-
201
- offset += NUM_BYTES_IN_DW;
202
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
203
- MEMTXATTRS_UNSPECIFIED, &res);
204
-
205
- if (res != MEMTX_OK) {
206
- return CMD_STALL;
207
- }
208
-
209
- size = (value & SIZE_MASK);
210
-
211
- offset += NUM_BYTES_IN_DW;
212
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
213
- MEMTXATTRS_UNSPECIFIED, &res);
214
-
215
- if (res != MEMTX_OK) {
216
- return CMD_STALL;
217
- }
218
-
219
- itt_addr = (value & ITTADDR_MASK) >> ITTADDR_SHIFT;
220
-
221
- valid = (value & CMD_FIELD_VALID_MASK);
222
+ devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
223
+ size = cmdpkt[1] & SIZE_MASK;
224
+ itt_addr = (cmdpkt[2] & ITTADDR_MASK) >> ITTADDR_SHIFT;
225
+ valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
226
227
if ((devid >= s->dt.num_entries) ||
228
(size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
229
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value,
230
return update_dte(s, devid, valid, size, itt_addr) ? CMD_CONTINUE : CMD_STALL;
231
}
232
233
-static ItsCmdResult process_movall(GICv3ITSState *s, uint64_t value,
234
- uint32_t offset)
235
+static ItsCmdResult process_movall(GICv3ITSState *s, const uint64_t *cmdpkt)
236
{
237
- AddressSpace *as = &s->gicv3->dma_as;
238
- MemTxResult res = MEMTX_OK;
239
uint64_t rd1, rd2;
240
241
- /* No fields in dwords 0 or 1 */
242
- offset += NUM_BYTES_IN_DW;
243
- offset += NUM_BYTES_IN_DW;
244
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
245
- MEMTXATTRS_UNSPECIFIED, &res);
246
- if (res != MEMTX_OK) {
247
- return CMD_STALL;
248
- }
249
+ rd1 = FIELD_EX64(cmdpkt[2], MOVALL_2, RDBASE1);
250
+ rd2 = FIELD_EX64(cmdpkt[3], MOVALL_3, RDBASE2);
251
252
- rd1 = FIELD_EX64(value, MOVALL_2, RDBASE1);
253
if (rd1 >= s->gicv3->num_cpu) {
254
qemu_log_mask(LOG_GUEST_ERROR,
255
"%s: RDBASE1 %" PRId64
256
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movall(GICv3ITSState *s, uint64_t value,
257
__func__, rd1, s->gicv3->num_cpu);
258
return CMD_CONTINUE;
259
}
260
-
261
- offset += NUM_BYTES_IN_DW;
262
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
263
- MEMTXATTRS_UNSPECIFIED, &res);
264
- if (res != MEMTX_OK) {
265
- return CMD_STALL;
266
- }
267
-
268
- rd2 = FIELD_EX64(value, MOVALL_3, RDBASE2);
269
if (rd2 >= s->gicv3->num_cpu) {
270
qemu_log_mask(LOG_GUEST_ERROR,
271
"%s: RDBASE2 %" PRId64
272
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movall(GICv3ITSState *s, uint64_t value,
273
return CMD_CONTINUE;
274
}
275
276
-static ItsCmdResult process_movi(GICv3ITSState *s, uint64_t value,
277
- uint32_t offset)
278
+static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
279
{
280
- AddressSpace *as = &s->gicv3->dma_as;
281
MemTxResult res = MEMTX_OK;
282
uint32_t devid, eventid, intid;
283
uint16_t old_icid, new_icid;
284
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, uint64_t value,
285
uint64_t num_eventids;
286
IteEntry ite = {};
287
288
- devid = FIELD_EX64(value, MOVI_0, DEVICEID);
289
-
290
- offset += NUM_BYTES_IN_DW;
291
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
292
- MEMTXATTRS_UNSPECIFIED, &res);
293
- if (res != MEMTX_OK) {
294
- return CMD_STALL;
295
- }
296
- eventid = FIELD_EX64(value, MOVI_1, EVENTID);
297
-
298
- offset += NUM_BYTES_IN_DW;
299
- value = address_space_ldq_le(as, s->cq.base_addr + offset,
300
- MEMTXATTRS_UNSPECIFIED, &res);
301
- if (res != MEMTX_OK) {
302
- return CMD_STALL;
303
- }
304
- new_icid = FIELD_EX64(value, MOVI_2, ICID);
305
+ devid = FIELD_EX64(cmdpkt[0], MOVI_0, DEVICEID);
306
+ eventid = FIELD_EX64(cmdpkt[1], MOVI_1, EVENTID);
307
+ new_icid = FIELD_EX64(cmdpkt[2], MOVI_2, ICID);
308
309
if (devid >= s->dt.num_entries) {
310
qemu_log_mask(LOG_GUEST_ERROR,
311
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
312
uint32_t wr_offset = 0;
313
uint32_t rd_offset = 0;
314
uint32_t cq_offset = 0;
315
- uint64_t data;
316
AddressSpace *as = &s->gicv3->dma_as;
317
- MemTxResult res = MEMTX_OK;
318
uint8_t cmd;
319
int i;
320
321
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
322
323
while (wr_offset != rd_offset) {
324
ItsCmdResult result = CMD_CONTINUE;
325
+ void *hostmem;
326
+ hwaddr buflen;
327
+ uint64_t cmdpkt[GITS_CMDQ_ENTRY_WORDS];
328
329
cq_offset = (rd_offset * GITS_CMDQ_ENTRY_SIZE);
330
- data = address_space_ldq_le(as, s->cq.base_addr + cq_offset,
331
- MEMTXATTRS_UNSPECIFIED, &res);
332
- if (res != MEMTX_OK) {
333
+
334
+ buflen = GITS_CMDQ_ENTRY_SIZE;
335
+ hostmem = address_space_map(as, s->cq.base_addr + cq_offset,
336
+ &buflen, false, MEMTXATTRS_UNSPECIFIED);
337
+ if (!hostmem || buflen != GITS_CMDQ_ENTRY_SIZE) {
338
+ if (hostmem) {
339
+ address_space_unmap(as, hostmem, buflen, false, 0);
340
+ }
341
s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, STALLED, 1);
342
qemu_log_mask(LOG_GUEST_ERROR,
343
"%s: could not read command at 0x%" PRIx64 "\n",
344
__func__, s->cq.base_addr + cq_offset);
345
break;
346
}
347
+ for (i = 0; i < ARRAY_SIZE(cmdpkt); i++) {
348
+ cmdpkt[i] = ldq_le_p(hostmem + i * sizeof(uint64_t));
349
+ }
350
+ address_space_unmap(as, hostmem, buflen, false, 0);
351
352
- cmd = (data & CMD_MASK);
353
+ cmd = cmdpkt[0] & CMD_MASK;
354
355
trace_gicv3_its_process_command(rd_offset, cmd);
356
357
switch (cmd) {
358
case GITS_CMD_INT:
359
- result = process_its_cmd(s, data, cq_offset, INTERRUPT);
360
+ result = process_its_cmd(s, cmdpkt, INTERRUPT);
361
break;
362
case GITS_CMD_CLEAR:
363
- result = process_its_cmd(s, data, cq_offset, CLEAR);
364
+ result = process_its_cmd(s, cmdpkt, CLEAR);
365
break;
366
case GITS_CMD_SYNC:
367
/*
368
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
369
*/
370
break;
371
case GITS_CMD_MAPD:
372
- result = process_mapd(s, data, cq_offset);
373
+ result = process_mapd(s, cmdpkt);
374
break;
375
case GITS_CMD_MAPC:
376
- result = process_mapc(s, cq_offset);
377
+ result = process_mapc(s, cmdpkt);
378
break;
379
case GITS_CMD_MAPTI:
380
- result = process_mapti(s, data, cq_offset, false);
381
+ result = process_mapti(s, cmdpkt, false);
382
break;
383
case GITS_CMD_MAPI:
384
- result = process_mapti(s, data, cq_offset, true);
385
+ result = process_mapti(s, cmdpkt, true);
386
break;
387
case GITS_CMD_DISCARD:
388
- result = process_its_cmd(s, data, cq_offset, DISCARD);
389
+ result = process_its_cmd(s, cmdpkt, DISCARD);
390
break;
391
case GITS_CMD_INV:
392
case GITS_CMD_INVALL:
393
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
394
}
395
break;
396
case GITS_CMD_MOVI:
397
- result = process_movi(s, data, cq_offset);
398
+ result = process_movi(s, cmdpkt);
399
break;
400
case GITS_CMD_MOVALL:
401
- result = process_movall(s, data, cq_offset);
402
+ result = process_movall(s, cmdpkt);
403
break;
404
default:
405
break;
406
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
407
{
408
GICv3ITSState *s = (GICv3ITSState *)opaque;
409
bool result = true;
410
- uint32_t devid = 0;
411
412
trace_gicv3_its_translation_write(offset, data, size, attrs.requester_id);
413
414
switch (offset) {
415
case GITS_TRANSLATER:
416
if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) {
417
- devid = attrs.requester_id;
418
- result = process_its_cmd(s, data, devid, NONE);
419
+ result = do_process_its_cmd(s, attrs.requester_id, data, NONE);
420
}
421
break;
422
default:
423
--
100
--
424
2.25.1
101
2.17.1
425
102
426
103
diff view generated by jsdifflib
1
Make the update_ite() struct use the new ITEntry struct, so that
1
The final part of the Memory Protection Controller we need to
2
callers don't need to assemble the in-memory ITE data themselves, and
2
implement is actually using the BLK_LUT data programmed by the
3
only get_ite() and update_ite() need to care about that in-memory
3
guest to determine whether to block the transaction or not.
4
layout. We can then drop the no-longer-used IteEntry struct
4
5
definition.
5
Since this means we now change transaction mappings when
6
the guest writes to BLK_LUT, we must also call the IOMMU
7
notifiers at that point.
6
8
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Eric Auger <eric.auger@redhat.com>
9
Message-id: 20220201193207.2771604-10-peter.maydell@linaro.org
11
Message-id: 20180620132032.28865-5-peter.maydell@linaro.org
10
---
12
---
11
hw/intc/arm_gicv3_its.c | 62 +++++++++++++++++++++--------------------
13
hw/misc/tz-mpc.c | 53 ++++++++++++++++++++++++++++++++++++++++++--
12
1 file changed, 32 insertions(+), 30 deletions(-)
14
hw/misc/trace-events | 1 +
15
2 files changed, 52 insertions(+), 2 deletions(-)
13
16
14
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
17
diff --git a/hw/misc/tz-mpc.c b/hw/misc/tz-mpc.c
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/arm_gicv3_its.c
19
--- a/hw/misc/tz-mpc.c
17
+++ b/hw/intc/arm_gicv3_its.c
20
+++ b/hw/misc/tz-mpc.c
18
@@ -XXX,XX +XXX,XX @@ typedef enum ItsCmdType {
21
@@ -XXX,XX +XXX,XX @@ static void tz_mpc_irq_update(TZMPC *s)
19
INTERRUPT = 3,
22
qemu_set_irq(s->irq, s->int_stat && s->int_en);
20
} ItsCmdType;
21
22
-typedef struct {
23
- uint32_t iteh;
24
- uint64_t itel;
25
-} IteEntry;
26
-
27
typedef struct DTEntry {
28
bool valid;
29
unsigned size;
30
@@ -XXX,XX +XXX,XX @@ static MemTxResult get_cte(GICv3ITSState *s, uint16_t icid, CTEntry *cte)
31
return MEMTX_OK;
32
}
23
}
33
24
34
+/*
25
+static void tz_mpc_iommu_notify(TZMPC *s, uint32_t lutidx,
35
+ * Update the Interrupt Table entry at index @evinted in the table specified
26
+ uint32_t oldlut, uint32_t newlut)
36
+ * by the dte @dte. Returns true on success, false if there was a memory
27
+{
37
+ * access error.
28
+ /* Called when the LUT word at lutidx has changed from oldlut to newlut;
38
+ */
29
+ * must call the IOMMU notifiers for the changed blocks.
39
static bool update_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
30
+ */
40
- IteEntry ite)
31
+ IOMMUTLBEntry entry = {
41
+ const ITEntry *ite)
32
+ .addr_mask = s->blocksize - 1,
33
+ };
34
+ hwaddr addr = lutidx * s->blocksize * 32;
35
+ int i;
36
+
37
+ for (i = 0; i < 32; i++, addr += s->blocksize) {
38
+ bool block_is_ns;
39
+
40
+ if (!((oldlut ^ newlut) & (1 << i))) {
41
+ continue;
42
+ }
43
+ /* This changes the mappings for both the S and the NS space,
44
+ * so we need to do four notifies: an UNMAP then a MAP for each.
45
+ */
46
+ block_is_ns = newlut & (1 << i);
47
+
48
+ trace_tz_mpc_iommu_notify(addr);
49
+ entry.iova = addr;
50
+ entry.translated_addr = addr;
51
+
52
+ entry.perm = IOMMU_NONE;
53
+ memory_region_notify_iommu(&s->upstream, IOMMU_IDX_S, entry);
54
+ memory_region_notify_iommu(&s->upstream, IOMMU_IDX_NS, entry);
55
+
56
+ entry.perm = IOMMU_RW;
57
+ if (block_is_ns) {
58
+ entry.target_as = &s->blocked_io_as;
59
+ } else {
60
+ entry.target_as = &s->downstream_as;
61
+ }
62
+ memory_region_notify_iommu(&s->upstream, IOMMU_IDX_S, entry);
63
+ if (block_is_ns) {
64
+ entry.target_as = &s->downstream_as;
65
+ } else {
66
+ entry.target_as = &s->blocked_io_as;
67
+ }
68
+ memory_region_notify_iommu(&s->upstream, IOMMU_IDX_NS, entry);
69
+ }
70
+}
71
+
72
static void tz_mpc_autoinc_idx(TZMPC *s, unsigned access_size)
42
{
73
{
43
AddressSpace *as = &s->gicv3->dma_as;
74
/* Auto-increment BLK_IDX if necessary */
44
MemTxResult res = MEMTX_OK;
75
@@ -XXX,XX +XXX,XX @@ static MemTxResult tz_mpc_reg_write(void *opaque, hwaddr addr,
45
hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
76
s->blk_idx = value % s->blk_max;
46
+ uint64_t itel = 0;
77
break;
47
+ uint32_t iteh = 0;
78
case A_BLK_LUT:
48
79
+ tz_mpc_iommu_notify(s, s->blk_idx, s->blk_lut[s->blk_idx], value);
49
- address_space_stq_le(as, iteaddr, ite.itel, MEMTXATTRS_UNSPECIFIED, &res);
80
s->blk_lut[s->blk_idx] = value;
50
-
81
tz_mpc_autoinc_idx(s, size);
51
- if (res == MEMTX_OK) {
82
break;
52
- address_space_stl_le(as, iteaddr + 8, ite.iteh,
83
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry tz_mpc_translate(IOMMUMemoryRegion *iommu,
53
- MEMTXATTRS_UNSPECIFIED, &res);
84
/* Look at the per-block configuration for this address, and
54
+ if (ite->valid) {
85
* return a TLB entry directing the transaction at either
55
+ itel = FIELD_DP64(itel, ITE_L, VALID, 1);
86
* downstream_as or blocked_io_as, as appropriate.
56
+ itel = FIELD_DP64(itel, ITE_L, INTTYPE, ite->inttype);
87
- * For the moment, always permit accesses.
57
+ itel = FIELD_DP64(itel, ITE_L, INTID, ite->intid);
88
+ * If the LUT cfg_ns bit is 1, only non-secure transactions
58
+ itel = FIELD_DP64(itel, ITE_L, ICID, ite->icid);
89
+ * may pass. If the bit is 0, only secure transactions may pass.
59
+ itel = FIELD_DP64(itel, ITE_L, VPEID, ite->vpeid);
90
*/
60
+ iteh = FIELD_DP32(iteh, ITE_H, DOORBELL, ite->doorbell);
91
- ok = true;
61
}
92
+ ok = tz_mpc_cfg_ns(s, addr) == (iommu_idx == IOMMU_IDX_NS);
62
+
93
63
+ address_space_stq_le(as, iteaddr, itel, MEMTXATTRS_UNSPECIFIED, &res);
94
trace_tz_mpc_translate(addr, flags,
64
if (res != MEMTX_OK) {
95
iommu_idx == IOMMU_IDX_S ? "S" : "NS",
65
return false;
96
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
66
- } else {
97
index XXXXXXX..XXXXXXX 100644
67
- return true;
98
--- a/hw/misc/trace-events
68
}
99
+++ b/hw/misc/trace-events
69
+ address_space_stl_le(as, iteaddr + 8, iteh, MEMTXATTRS_UNSPECIFIED, &res);
100
@@ -XXX,XX +XXX,XX @@ tz_mpc_reg_write(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs wri
70
+ return res == MEMTX_OK;
101
tz_mpc_mem_blocked_read(uint64_t addr, unsigned size, bool secure) "TZ MPC blocked read: offset 0x%" PRIx64 " size %u secure %d"
71
}
102
tz_mpc_mem_blocked_write(uint64_t addr, uint64_t data, unsigned size, bool secure) "TZ MPC blocked write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
72
103
tz_mpc_translate(uint64_t addr, int flags, const char *idx, const char *res) "TZ MPC translate: addr 0x%" PRIx64 " flags 0x%x iommu_idx %s: %s"
73
/*
104
+tz_mpc_iommu_notify(uint64_t addr) "TZ MPC iommu: notifying UNMAP/MAP for 0x%" PRIx64
74
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
105
75
}
106
# hw/misc/tz-ppc.c
76
107
tz_ppc_reset(void) "TZ PPC: reset"
77
if (cmd == DISCARD) {
78
- IteEntry itee = {};
79
+ ITEntry ite = {};
80
/* remove mapping from interrupt translation table */
81
- return update_ite(s, eventid, &dte, itee) ? CMD_CONTINUE : CMD_STALL;
82
+ ite.valid = false;
83
+ return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE : CMD_STALL;
84
}
85
return CMD_CONTINUE;
86
}
87
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
88
uint64_t num_eventids;
89
uint32_t num_intids;
90
uint16_t icid = 0;
91
- IteEntry ite = {};
92
DTEntry dte;
93
+ ITEntry ite;
94
95
devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
96
eventid = cmdpkt[1] & EVENTID_MASK;
97
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
98
}
99
100
/* add ite entry to interrupt translation table */
101
- ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, true);
102
- ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
103
- ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid);
104
- ite.itel = FIELD_DP64(ite.itel, ITE_L, ICID, icid);
105
- ite.iteh = FIELD_DP32(ite.iteh, ITE_H, DOORBELL, INTID_SPURIOUS);
106
-
107
- return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
108
+ ite.valid = true;
109
+ ite.inttype = ITE_INTTYPE_PHYSICAL;
110
+ ite.intid = pIntid;
111
+ ite.icid = icid;
112
+ ite.doorbell = INTID_SPURIOUS;
113
+ ite.vpeid = 0;
114
+ return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE : CMD_STALL;
115
}
116
117
/*
118
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
119
uint32_t devid, eventid;
120
uint16_t new_icid;
121
uint64_t num_eventids;
122
- IteEntry ite = {};
123
DTEntry dte;
124
CTEntry old_cte, new_cte;
125
ITEntry old_ite;
126
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
127
}
128
129
/* Update the ICID field in the interrupt translation table entry */
130
- ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, 1);
131
- ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
132
- ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, old_ite.intid);
133
- ite.itel = FIELD_DP64(ite.itel, ITE_L, ICID, new_icid);
134
- ite.iteh = FIELD_DP32(ite.iteh, ITE_H, DOORBELL, INTID_SPURIOUS);
135
- return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
136
+ old_ite.icid = new_icid;
137
+ return update_ite(s, eventid, &dte, &old_ite) ? CMD_CONTINUE : CMD_STALL;
138
}
139
140
/*
141
--
108
--
142
2.25.1
109
2.17.1
143
110
144
111
diff view generated by jsdifflib
1
Instead of setting the CPU psci-conduit and start-powered-off
1
Implement the SECMPCINTSTATUS register. This is the only register
2
properties in the xlnx-versal-virt board code, set the arm_boot_info
2
in the security controller that deals with Memory Protection
3
psci_conduit field so that the boot.c code can do it.
3
Controllers, and it simply provides a read-only view of the
4
4
interrupt lines from the various MPCs in the system.
5
This will fix a corner case where we were incorrectly enabling PSCI
6
emulation when booting guest code into EL3 because it was an ELF file
7
passed to -kernel. (EL3 guest code started via -bios, -pflash, or
8
the generic loader was already being run with PSCI emulation
9
disabled.)
10
11
Note that EL3 guest code has no way to turn on the secondary CPUs
12
because there's no emulated power controller, but this was already
13
true for EL3 guest code run via -bios, -pflash, or the generic
14
loader.
15
5
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Message-id: 20180620132032.28865-6-peter.maydell@linaro.org
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
20
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
21
Tested-by: Cédric Le Goater <clg@kaod.org>
22
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
23
Message-id: 20220127154639.2090164-8-peter.maydell@linaro.org
24
---
8
---
25
include/hw/arm/xlnx-versal.h | 1 -
9
include/hw/misc/iotkit-secctl.h | 8 +++++++
26
hw/arm/xlnx-versal-virt.c | 6 ++++--
10
hw/misc/iotkit-secctl.c | 38 +++++++++++++++++++++++++++++++--
27
hw/arm/xlnx-versal.c | 5 +----
11
2 files changed, 44 insertions(+), 2 deletions(-)
28
3 files changed, 5 insertions(+), 7 deletions(-)
29
12
30
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
13
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
31
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
32
--- a/include/hw/arm/xlnx-versal.h
15
--- a/include/hw/misc/iotkit-secctl.h
33
+++ b/include/hw/arm/xlnx-versal.h
16
+++ b/include/hw/misc/iotkit-secctl.h
34
@@ -XXX,XX +XXX,XX @@ struct Versal {
17
@@ -XXX,XX +XXX,XX @@
35
18
* + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
36
struct {
19
* + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
37
MemoryRegion *mr_ddr;
20
* + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
38
- uint32_t psci_conduit;
21
+ * Controlling the MPC in the IoTKit:
39
} cfg;
22
+ * + named GPIO input mpc_status
23
+ * Controlling each of the 16 expansion MPCs which a system using the IoTKit
24
+ * might provide:
25
+ * + named GPIO inputs mpcexp_status[0..15]
26
*/
27
28
#ifndef IOTKIT_SECCTL_H
29
@@ -XXX,XX +XXX,XX @@
30
#define IOTS_NUM_APB_PPC 2
31
#define IOTS_NUM_APB_EXP_PPC 4
32
#define IOTS_NUM_AHB_EXP_PPC 4
33
+#define IOTS_NUM_EXP_MPC 16
34
+#define IOTS_NUM_MPC 1
35
36
typedef struct IoTKitSecCtl IoTKitSecCtl;
37
38
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
39
uint32_t secrespcfg;
40
uint32_t nsccfg;
41
uint32_t brginten;
42
+ uint32_t mpcintstatus;
43
44
IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
45
IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
46
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/misc/iotkit-secctl.c
49
+++ b/hw/misc/iotkit-secctl.c
50
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
51
case A_NSCCFG:
52
r = s->nsccfg;
53
break;
54
+ case A_SECMPCINTSTATUS:
55
+ r = s->mpcintstatus;
56
+ break;
57
case A_SECPPCINTSTAT:
58
r = s->secppcintstat;
59
break;
60
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
61
case A_APBSPPPCEXP3:
62
r = s->apbexp[offset_to_ppc_idx(offset)].sp;
63
break;
64
- case A_SECMPCINTSTATUS:
65
case A_SECMSCINTSTAT:
66
case A_SECMSCINTEN:
67
case A_NSMSCEXP:
68
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_reset(DeviceState *dev)
69
foreach_ppc(s, iotkit_secctl_reset_ppc);
70
}
71
72
+static void iotkit_secctl_mpc_status(void *opaque, int n, int level)
73
+{
74
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
75
+
76
+ s->mpcintstatus = deposit32(s->mpcintstatus, 0, 1, !!level);
77
+}
78
+
79
+static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level)
80
+{
81
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
82
+
83
+ s->mpcintstatus = deposit32(s->mpcintstatus, n + 16, 1, !!level);
84
+}
85
+
86
static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
87
{
88
IoTKitSecCtlPPC *ppc = opaque;
89
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
90
qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
91
qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
92
93
+ qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status", 1);
94
+ qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status,
95
+ "mpcexp_status", IOTS_NUM_EXP_MPC);
96
+
97
memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
98
s, "iotkit-secctl-s-regs", 0x1000);
99
memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
100
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_secctl_ppc_vmstate = {
101
}
40
};
102
};
41
103
42
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
104
+static const VMStateDescription iotkit_secctl_mpcintstatus_vmstate = {
43
index XXXXXXX..XXXXXXX 100644
105
+ .name = "iotkit-secctl-mpcintstatus",
44
--- a/hw/arm/xlnx-versal-virt.c
106
+ .version_id = 1,
45
+++ b/hw/arm/xlnx-versal-virt.c
107
+ .minimum_version_id = 1,
46
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
108
+ .fields = (VMStateField[]) {
47
* When loading an OS, we turn on QEMU's PSCI implementation with SMC
109
+ VMSTATE_UINT32(mpcintstatus, IoTKitSecCtl),
48
* as the PSCI conduit. When there's no -kernel, we assume the user
110
+ VMSTATE_END_OF_LIST()
49
* provides EL3 firmware to handle PSCI.
111
+ }
50
+ *
112
+};
51
+ * Even if the user provides a kernel filename, arm_load_kernel()
113
+
52
+ * may suppress PSCI if it's going to boot that guest code at EL3.
114
static const VMStateDescription iotkit_secctl_vmstate = {
53
*/
115
.name = "iotkit-secctl",
54
if (machine->kernel_filename) {
116
.version_id = 1,
55
psci_conduit = QEMU_PSCI_CONDUIT_SMC;
117
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_secctl_vmstate = {
56
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
118
VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1,
57
TYPE_XLNX_VERSAL);
119
iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
58
object_property_set_link(OBJECT(&s->soc), "ddr", OBJECT(machine->ram),
120
VMSTATE_END_OF_LIST()
59
&error_abort);
121
- }
60
- object_property_set_int(OBJECT(&s->soc), "psci-conduit", psci_conduit,
122
+ },
61
- &error_abort);
123
+ .subsections = (const VMStateDescription*[]) {
62
sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
124
+ &iotkit_secctl_mpcintstatus_vmstate,
63
125
+ NULL
64
fdt_create(s);
126
+ },
65
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
66
s->binfo.loader_start = 0x0;
67
s->binfo.get_dtb = versal_virt_get_dtb;
68
s->binfo.modify_dtb = versal_virt_modify_dtb;
69
+ s->binfo.psci_conduit = psci_conduit;
70
if (machine->kernel_filename) {
71
arm_load_kernel(&s->soc.fpd.apu.cpu[0], machine, &s->binfo);
72
} else {
73
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/arm/xlnx-versal.c
76
+++ b/hw/arm/xlnx-versal.c
77
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
78
object_initialize_child(OBJECT(s), "apu-cpu[*]", &s->fpd.apu.cpu[i],
79
XLNX_VERSAL_ACPU_TYPE);
80
obj = OBJECT(&s->fpd.apu.cpu[i]);
81
- object_property_set_int(obj, "psci-conduit", s->cfg.psci_conduit,
82
- &error_abort);
83
if (i) {
84
- /* Secondary CPUs start in PSCI powered-down state */
85
+ /* Secondary CPUs start in powered-down state */
86
object_property_set_bool(obj, "start-powered-off", true,
87
&error_abort);
88
}
89
@@ -XXX,XX +XXX,XX @@ static void versal_init(Object *obj)
90
static Property versal_properties[] = {
91
DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION,
92
MemoryRegion *),
93
- DEFINE_PROP_UINT32("psci-conduit", Versal, cfg.psci_conduit, 0),
94
DEFINE_PROP_END_OF_LIST()
95
};
127
};
96
128
129
static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
97
--
130
--
98
2.25.1
131
2.17.1
99
132
100
133
diff view generated by jsdifflib
1
In the MAPC command, if V=0 this is a request to delete a collection
1
Wire up the one MPC that is part of the IoTKit itself. For the
2
table entry and the rdbase field of the command packet will not be
2
moment we don't wire up its interrupt line.
3
used. In particular, the specification says that the "UNPREDICTABLE
4
if rdbase is not valid" only applies for V=1.
5
6
We were doing a check-and-log-guest-error on rdbase regardless of
7
whether the V bit was set, and also (harmlessly but confusingly)
8
storing the contents of the rdbase field into the updated collection
9
table entry. Update the code so that if V=0 we don't check or use
10
the rdbase field value.
11
3
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
14
Message-id: 20220201193207.2771604-12-peter.maydell@linaro.org
6
Message-id: 20180620132032.28865-7-peter.maydell@linaro.org
15
---
7
---
16
hw/intc/arm_gicv3_its.c | 24 ++++++++++++------------
8
include/hw/arm/iotkit.h | 2 ++
17
1 file changed, 12 insertions(+), 12 deletions(-)
9
hw/arm/iotkit.c | 38 +++++++++++++++++++++++++++-----------
10
2 files changed, 29 insertions(+), 11 deletions(-)
18
11
19
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
12
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
20
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/intc/arm_gicv3_its.c
14
--- a/include/hw/arm/iotkit.h
22
+++ b/hw/intc/arm_gicv3_its.c
15
+++ b/include/hw/arm/iotkit.h
23
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt)
16
@@ -XXX,XX +XXX,XX @@
24
CTEntry cte;
17
#include "hw/arm/armv7m.h"
25
18
#include "hw/misc/iotkit-secctl.h"
26
icid = cmdpkt[2] & ICID_MASK;
19
#include "hw/misc/tz-ppc.h"
20
+#include "hw/misc/tz-mpc.h"
21
#include "hw/timer/cmsdk-apb-timer.h"
22
#include "hw/misc/unimp.h"
23
#include "hw/or-irq.h"
24
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
25
IoTKitSecCtl secctl;
26
TZPPC apb_ppc0;
27
TZPPC apb_ppc1;
28
+ TZMPC mpc;
29
CMSDKAPBTIMER timer0;
30
CMSDKAPBTIMER timer1;
31
qemu_or_irq ppc_irq_orgate;
32
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/iotkit.c
35
+++ b/hw/arm/iotkit.c
36
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
37
TYPE_TZ_PPC);
38
init_sysbus_child(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
39
TYPE_TZ_PPC);
40
+ init_sysbus_child(obj, "mpc", &s->mpc, sizeof(s->mpc), TYPE_TZ_MPC);
41
init_sysbus_child(obj, "timer0", &s->timer0, sizeof(s->timer0),
42
TYPE_CMSDK_APB_TIMER);
43
init_sysbus_child(obj, "timer1", &s->timer1, sizeof(s->timer1),
44
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
45
*/
46
make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000);
47
48
- /* This RAM should be behind a Memory Protection Controller, but we
49
- * don't implement that yet.
50
- */
51
- memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &err);
52
- if (err) {
53
- error_propagate(errp, err);
54
- return;
55
- }
56
- memory_region_add_subregion(&s->container, 0x20000000, &s->sram0);
57
58
/* Security controller */
59
object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
60
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
61
qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0,
62
qdev_get_gpio_in(dev_splitter, 0));
63
64
+ /* This RAM lives behind the Memory Protection Controller */
65
+ memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &err);
66
+ if (err) {
67
+ error_propagate(errp, err);
68
+ return;
69
+ }
70
+ object_property_set_link(OBJECT(&s->mpc), OBJECT(&s->sram0),
71
+ "downstream", &err);
72
+ if (err) {
73
+ error_propagate(errp, err);
74
+ return;
75
+ }
76
+ object_property_set_bool(OBJECT(&s->mpc), true, "realized", &err);
77
+ if (err) {
78
+ error_propagate(errp, err);
79
+ return;
80
+ }
81
+ /* Map the upstream end of the MPC into the right place... */
82
+ memory_region_add_subregion(&s->container, 0x20000000,
83
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc),
84
+ 1));
85
+ /* ...and its register interface */
86
+ memory_region_add_subregion(&s->container, 0x50083000,
87
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc),
88
+ 0));
89
+
90
/* Devices behind APB PPC0:
91
* 0x40000000: timer0
92
* 0x40001000: timer1
93
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
94
create_unimplemented_device("NS watchdog", 0x40081000, 0x1000);
95
create_unimplemented_device("S watchdog", 0x50081000, 0x1000);
96
97
- create_unimplemented_device("SRAM0 MPC", 0x50083000, 0x1000);
27
-
98
-
28
- cte.rdbase = (cmdpkt[2] & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
99
for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
29
- cte.rdbase &= RDBASE_PROCNUM_MASK;
100
Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
30
-
31
cte.valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
32
+ if (cte.valid) {
33
+ cte.rdbase = (cmdpkt[2] & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
34
+ cte.rdbase &= RDBASE_PROCNUM_MASK;
35
+ } else {
36
+ cte.rdbase = 0;
37
+ }
38
39
- if ((icid >= s->ct.num_entries) || (cte.rdbase >= s->gicv3->num_cpu)) {
40
+ if (icid >= s->ct.num_entries) {
41
+ qemu_log_mask(LOG_GUEST_ERROR, "ITS MAPC: invalid ICID 0x%d", icid);
42
+ return CMD_CONTINUE;
43
+ }
44
+ if (cte.valid && cte.rdbase >= s->gicv3->num_cpu) {
45
qemu_log_mask(LOG_GUEST_ERROR,
46
- "ITS MAPC: invalid collection table attributes "
47
- "icid %d rdbase %u\n", icid, cte.rdbase);
48
- /*
49
- * in this implementation, in case of error
50
- * we ignore this command and move onto the next
51
- * command in the queue
52
- */
53
+ "ITS MAPC: invalid RDBASE %u ", cte.rdbase);
54
return CMD_CONTINUE;
55
}
56
101
57
--
102
--
58
2.25.1
103
2.17.1
59
104
60
105
diff view generated by jsdifflib
1
Make update_cte() take a CTEntry struct rather than all the fields
1
The interrupt outputs from the MPC in the IoTKit and the expansion
2
of the new CTE as separate arguments.
2
MPCs in the board must be wired up to the security controller, and
3
3
also all ORed together to produce a single line to the NVIC.
4
This brings it into line with the update_dte() API.
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: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Message-id: 20220201193207.2771604-6-peter.maydell@linaro.org
7
Message-id: 20180620132032.28865-8-peter.maydell@linaro.org
9
---
8
---
10
hw/intc/arm_gicv3_its.c | 32 +++++++++++++++++---------------
9
include/hw/arm/iotkit.h | 6 ++++
11
1 file changed, 17 insertions(+), 15 deletions(-)
10
hw/arm/iotkit.c | 74 +++++++++++++++++++++++++++++++++++++++++
11
2 files changed, 80 insertions(+)
12
12
13
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
13
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/intc/arm_gicv3_its.c
15
--- a/include/hw/arm/iotkit.h
16
+++ b/hw/intc/arm_gicv3_its.c
16
+++ b/include/hw/arm/iotkit.h
17
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
17
@@ -XXX,XX +XXX,XX @@
18
return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
18
* + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
19
* + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
20
* + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
21
+ * Controlling each of the 16 expansion MPCs which a system using the IoTKit
22
+ * might provide:
23
+ * + named GPIO inputs mpcexp_status[0..15]
24
*/
25
26
#ifndef IOTKIT_H
27
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
28
qemu_or_irq ppc_irq_orgate;
29
SplitIRQ sec_resp_splitter;
30
SplitIRQ ppc_irq_splitter[NUM_PPCS];
31
+ SplitIRQ mpc_irq_splitter[IOTS_NUM_EXP_MPC + IOTS_NUM_MPC];
32
+ qemu_or_irq mpc_irq_orgate;
33
34
UnimplementedDeviceState dualtimer;
35
UnimplementedDeviceState s32ktimer;
36
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
37
qemu_irq nsc_cfg_in;
38
39
qemu_irq irq_status_in[NUM_EXTERNAL_PPCS];
40
+ qemu_irq mpcexp_status_in[IOTS_NUM_EXP_MPC];
41
42
uint32_t nsccfg;
43
44
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/iotkit.c
47
+++ b/hw/arm/iotkit.c
48
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
49
init_sysbus_child(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
50
TYPE_TZ_PPC);
51
init_sysbus_child(obj, "mpc", &s->mpc, sizeof(s->mpc), TYPE_TZ_MPC);
52
+ object_initialize(&s->mpc_irq_orgate, sizeof(s->mpc_irq_orgate),
53
+ TYPE_OR_IRQ);
54
+ object_property_add_child(obj, "mpc-irq-orgate",
55
+ OBJECT(&s->mpc_irq_orgate), &error_abort);
56
+ for (i = 0; i < ARRAY_SIZE(s->mpc_irq_splitter); i++) {
57
+ char *name = g_strdup_printf("mpc-irq-splitter-%d", i);
58
+ SplitIRQ *splitter = &s->mpc_irq_splitter[i];
59
+
60
+ object_initialize(splitter, sizeof(*splitter), TYPE_SPLIT_IRQ);
61
+ object_property_add_child(obj, name, OBJECT(splitter), &error_abort);
62
+ g_free(name);
63
+ }
64
init_sysbus_child(obj, "timer0", &s->timer0, sizeof(s->timer0),
65
TYPE_CMSDK_APB_TIMER);
66
init_sysbus_child(obj, "timer1", &s->timer1, sizeof(s->timer1),
67
@@ -XXX,XX +XXX,XX @@ static void iotkit_exp_irq(void *opaque, int n, int level)
68
qemu_set_irq(s->exp_irqs[n], level);
19
}
69
}
20
70
21
-static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
71
+static void iotkit_mpcexp_status(void *opaque, int n, int level)
22
- uint64_t rdbase)
72
+{
23
+/*
73
+ IoTKit *s = IOTKIT(opaque);
24
+ * Update the Collection Table entry for @icid to @cte. Returns true
74
+ qemu_set_irq(s->mpcexp_status_in[n], level);
25
+ * on success, false if there was a memory access error.
75
+}
26
+ */
76
+
27
+static bool update_cte(GICv3ITSState *s, uint16_t icid, const CTEntry *cte)
77
static void iotkit_realize(DeviceState *dev, Error **errp)
28
{
78
{
29
AddressSpace *as = &s->gicv3->dma_as;
79
IoTKit *s = IOTKIT(dev);
30
uint64_t entry_addr;
80
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
31
- uint64_t cte = 0;
81
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc),
32
+ uint64_t cteval = 0;
82
0));
33
MemTxResult res = MEMTX_OK;
83
34
84
+ /* We must OR together lines from the MPC splitters to go to the NVIC */
35
if (!s->ct.valid) {
85
+ object_property_set_int(OBJECT(&s->mpc_irq_orgate),
36
return true;
86
+ IOTS_NUM_EXP_MPC + IOTS_NUM_MPC, "num-lines", &err);
87
+ if (err) {
88
+ error_propagate(errp, err);
89
+ return;
90
+ }
91
+ object_property_set_bool(OBJECT(&s->mpc_irq_orgate), true,
92
+ "realized", &err);
93
+ if (err) {
94
+ error_propagate(errp, err);
95
+ return;
96
+ }
97
+ qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0,
98
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 9));
99
+
100
/* Devices behind APB PPC0:
101
* 0x40000000: timer0
102
* 0x40001000: timer1
103
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
104
g_free(gpioname);
37
}
105
}
38
106
39
- if (valid) {
107
+ /* Wire up the splitters for the MPC IRQs */
40
+ if (cte->valid) {
108
+ for (i = 0; i < IOTS_NUM_EXP_MPC + IOTS_NUM_MPC; i++) {
41
/* add mapping entry to collection table */
109
+ SplitIRQ *splitter = &s->mpc_irq_splitter[i];
42
- cte = FIELD_DP64(cte, CTE, VALID, 1);
110
+ DeviceState *dev_splitter = DEVICE(splitter);
43
- cte = FIELD_DP64(cte, CTE, RDBASE, rdbase);
111
+
44
+ cteval = FIELD_DP64(cteval, CTE, VALID, 1);
112
+ object_property_set_int(OBJECT(splitter), 2, "num-lines", &err);
45
+ cteval = FIELD_DP64(cteval, CTE, RDBASE, cte->rdbase);
113
+ if (err) {
46
}
114
+ error_propagate(errp, err);
47
115
+ return;
48
entry_addr = table_entry_addr(s, &s->ct, icid, &res);
116
+ }
49
@@ -XXX,XX +XXX,XX @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
117
+ object_property_set_bool(OBJECT(splitter), true, "realized", &err);
50
return true;
118
+ if (err) {
51
}
119
+ error_propagate(errp, err);
52
120
+ return;
53
- address_space_stq_le(as, entry_addr, cte, MEMTXATTRS_UNSPECIFIED, &res);
121
+ }
54
+ address_space_stq_le(as, entry_addr, cteval, MEMTXATTRS_UNSPECIFIED, &res);
122
+
55
return res == MEMTX_OK;
123
+ if (i < IOTS_NUM_EXP_MPC) {
56
}
124
+ /* Splitter input is from GPIO input line */
57
125
+ s->mpcexp_status_in[i] = qdev_get_gpio_in(dev_splitter, 0);
58
static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt)
126
+ qdev_connect_gpio_out(dev_splitter, 0,
59
{
127
+ qdev_get_gpio_in_named(dev_secctl,
60
uint16_t icid;
128
+ "mpcexp_status", i));
61
- uint64_t rdbase;
129
+ } else {
62
- bool valid;
130
+ /* Splitter input is from our own MPC */
63
+ CTEntry cte;
131
+ qdev_connect_gpio_out_named(DEVICE(&s->mpc), "irq", 0,
64
132
+ qdev_get_gpio_in(dev_splitter, 0));
65
icid = cmdpkt[2] & ICID_MASK;
133
+ qdev_connect_gpio_out(dev_splitter, 0,
66
134
+ qdev_get_gpio_in_named(dev_secctl,
67
- rdbase = (cmdpkt[2] & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
135
+ "mpc_status", 0));
68
- rdbase &= RDBASE_PROCNUM_MASK;
136
+ }
69
+ cte.rdbase = (cmdpkt[2] & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
137
+
70
+ cte.rdbase &= RDBASE_PROCNUM_MASK;
138
+ qdev_connect_gpio_out(dev_splitter, 1,
71
139
+ qdev_get_gpio_in(DEVICE(&s->mpc_irq_orgate), i));
72
- valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
140
+ }
73
+ cte.valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
141
+ /* Create GPIO inputs which will pass the line state for our
74
142
+ * mpcexp_irq inputs to the correct splitter devices.
75
- if ((icid >= s->ct.num_entries) || (rdbase >= s->gicv3->num_cpu)) {
143
+ */
76
+ if ((icid >= s->ct.num_entries) || (cte.rdbase >= s->gicv3->num_cpu)) {
144
+ qdev_init_gpio_in_named(dev, iotkit_mpcexp_status, "mpcexp_status",
77
qemu_log_mask(LOG_GUEST_ERROR,
145
+ IOTS_NUM_EXP_MPC);
78
"ITS MAPC: invalid collection table attributes "
146
+
79
- "icid %d rdbase %" PRIu64 "\n", icid, rdbase);
147
iotkit_forward_sec_resp_cfg(s);
80
+ "icid %d rdbase %u\n", icid, cte.rdbase);
148
81
/*
149
system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
82
* in this implementation, in case of error
83
* we ignore this command and move onto the next
84
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt)
85
return CMD_CONTINUE;
86
}
87
88
- return update_cte(s, icid, valid, rdbase) ? CMD_CONTINUE : CMD_STALL;
89
+ return update_cte(s, icid, &cte) ? CMD_CONTINUE : CMD_STALL;
90
}
91
92
/*
93
--
150
--
94
2.25.1
151
2.17.1
95
152
96
153
diff view generated by jsdifflib
1
Make update_dte() take a DTEntry struct rather than all the fields of
1
Instantiate and wire up the Memory Protection Controllers
2
the new DTE as separate arguments.
2
in the MPS2 board itself.
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Message-id: 20220201193207.2771604-4-peter.maydell@linaro.org
6
Message-id: 20180620132032.28865-9-peter.maydell@linaro.org
7
---
7
---
8
hw/intc/arm_gicv3_its.c | 35 ++++++++++++++++++-----------------
8
hw/arm/mps2-tz.c | 71 ++++++++++++++++++++++++++++++------------------
9
1 file changed, 18 insertions(+), 17 deletions(-)
9
1 file changed, 44 insertions(+), 27 deletions(-)
10
10
11
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
11
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
12
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/intc/arm_gicv3_its.c
13
--- a/hw/arm/mps2-tz.c
14
+++ b/hw/intc/arm_gicv3_its.c
14
+++ b/hw/arm/mps2-tz.c
15
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt)
15
@@ -XXX,XX +XXX,XX @@
16
return update_cte(s, icid, valid, rdbase) ? CMD_CONTINUE : CMD_STALL;
16
#include "hw/timer/cmsdk-apb-timer.h"
17
#include "hw/misc/mps2-scc.h"
18
#include "hw/misc/mps2-fpgaio.h"
19
+#include "hw/misc/tz-mpc.h"
20
#include "hw/arm/iotkit.h"
21
#include "hw/devices.h"
22
#include "net/net.h"
23
@@ -XXX,XX +XXX,XX @@ typedef struct {
24
25
IoTKit iotkit;
26
MemoryRegion psram;
27
- MemoryRegion ssram1;
28
+ MemoryRegion ssram[3];
29
MemoryRegion ssram1_m;
30
- MemoryRegion ssram23;
31
MPS2SCC scc;
32
MPS2FPGAIO fpgaio;
33
TZPPC ppc[5];
34
- UnimplementedDeviceState ssram_mpc[3];
35
+ TZMPC ssram_mpc[3];
36
UnimplementedDeviceState spi[5];
37
UnimplementedDeviceState i2c[4];
38
UnimplementedDeviceState i2s_audio;
39
@@ -XXX,XX +XXX,XX @@ typedef struct {
40
/* Main SYSCLK frequency in Hz */
41
#define SYSCLK_FRQ 20000000
42
43
-/* Initialize the auxiliary RAM region @mr and map it into
44
- * the memory map at @base.
45
- */
46
-static void make_ram(MemoryRegion *mr, const char *name,
47
- hwaddr base, hwaddr size)
48
-{
49
- memory_region_init_ram(mr, NULL, name, size, &error_fatal);
50
- memory_region_add_subregion(get_system_memory(), base, mr);
51
-}
52
-
53
/* Create an alias of an entire original MemoryRegion @orig
54
* located at @base in the memory map.
55
*/
56
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
57
return sysbus_mmio_get_region(s, 0);
17
}
58
}
18
59
19
-static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
60
+static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
20
- uint8_t size, uint64_t itt_addr)
61
+ const char *name, hwaddr size)
21
+/*
62
+{
22
+ * Update the Device Table entry for @devid to @dte. Returns true
63
+ TZMPC *mpc = opaque;
23
+ * on success, false if there was a memory access error.
64
+ int i = mpc - &mms->ssram_mpc[0];
24
+ */
65
+ MemoryRegion *ssram = &mms->ssram[i];
25
+static bool update_dte(GICv3ITSState *s, uint32_t devid, const DTEntry *dte)
66
+ MemoryRegion *upstream;
67
+ char *mpcname = g_strdup_printf("%s-mpc", name);
68
+ static uint32_t ramsize[] = { 0x00400000, 0x00200000, 0x00200000 };
69
+ static uint32_t rambase[] = { 0x00000000, 0x28000000, 0x28200000 };
70
+
71
+ memory_region_init_ram(ssram, NULL, name, ramsize[i], &error_fatal);
72
+
73
+ init_sysbus_child(OBJECT(mms), mpcname, mpc,
74
+ sizeof(mms->ssram_mpc[0]), TYPE_TZ_MPC);
75
+ object_property_set_link(OBJECT(mpc), OBJECT(ssram),
76
+ "downstream", &error_fatal);
77
+ object_property_set_bool(OBJECT(mpc), true, "realized", &error_fatal);
78
+ /* Map the upstream end of the MPC into system memory */
79
+ upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1);
80
+ memory_region_add_subregion(get_system_memory(), rambase[i], upstream);
81
+ /* and connect its interrupt to the IoTKit */
82
+ qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0,
83
+ qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
84
+ "mpcexp_status", i));
85
+
86
+ /* The first SSRAM is a special case as it has an alias; accesses to
87
+ * the alias region at 0x00400000 must also go to the MPC upstream.
88
+ */
89
+ if (i == 0) {
90
+ make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", upstream, 0x00400000);
91
+ }
92
+
93
+ g_free(mpcname);
94
+ /* Return the register interface MR for our caller to map behind the PPC */
95
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
96
+}
97
+
98
static void mps2tz_common_init(MachineState *machine)
26
{
99
{
27
AddressSpace *as = &s->gicv3->dma_as;
100
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
28
uint64_t entry_addr;
101
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
29
- uint64_t dte = 0;
102
NULL, "mps.ram", 0x01000000);
30
+ uint64_t dteval = 0;
103
memory_region_add_subregion(system_memory, 0x80000000, &mms->psram);
31
MemTxResult res = MEMTX_OK;
104
32
105
- /* The SSRAM memories should all be behind Memory Protection Controllers,
33
if (s->dt.valid) {
106
- * but we don't implement that yet.
34
- if (valid) {
107
- */
35
+ if (dte->valid) {
108
- make_ram(&mms->ssram1, "mps.ssram1", 0x00000000, 0x00400000);
36
/* add mapping entry to device table */
109
- make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x00400000);
37
- dte = FIELD_DP64(dte, DTE, VALID, 1);
110
-
38
- dte = FIELD_DP64(dte, DTE, SIZE, size);
111
- make_ram(&mms->ssram23, "mps.ssram23", 0x28000000, 0x00400000);
39
- dte = FIELD_DP64(dte, DTE, ITTADDR, itt_addr);
112
-
40
+ dteval = FIELD_DP64(dteval, DTE, VALID, 1);
113
/* The overflow IRQs for all UARTs are ORed together.
41
+ dteval = FIELD_DP64(dteval, DTE, SIZE, dte->size);
114
* Tx, Rx and "combined" IRQs are sent to the NVIC separately.
42
+ dteval = FIELD_DP64(dteval, DTE, ITTADDR, dte->ittaddr);
115
* Create the OR gate for this.
43
}
116
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
44
} else {
117
const PPCInfo ppcs[] = { {
45
return true;
118
.name = "apb_ppcexp0",
46
@@ -XXX,XX +XXX,XX @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
119
.ports = {
47
/* No L2 table for this index: discard write and continue */
120
- { "ssram-mpc0", make_unimp_dev, &mms->ssram_mpc[0],
48
return true;
121
- 0x58007000, 0x1000 },
49
}
122
- { "ssram-mpc1", make_unimp_dev, &mms->ssram_mpc[1],
50
- address_space_stq_le(as, entry_addr, dte, MEMTXATTRS_UNSPECIFIED, &res);
123
- 0x58008000, 0x1000 },
51
+ address_space_stq_le(as, entry_addr, dteval, MEMTXATTRS_UNSPECIFIED, &res);
124
- { "ssram-mpc2", make_unimp_dev, &mms->ssram_mpc[2],
52
return res == MEMTX_OK;
125
- 0x58009000, 0x1000 },
53
}
126
+ { "ssram-0", make_mpc, &mms->ssram_mpc[0], 0x58007000, 0x1000 },
54
127
+ { "ssram-1", make_mpc, &mms->ssram_mpc[1], 0x58008000, 0x1000 },
55
static ItsCmdResult process_mapd(GICv3ITSState *s, const uint64_t *cmdpkt)
128
+ { "ssram-2", make_mpc, &mms->ssram_mpc[2], 0x58009000, 0x1000 },
56
{
129
},
57
uint32_t devid;
130
}, {
58
- uint8_t size;
131
.name = "apb_ppcexp1",
59
- uint64_t itt_addr;
60
- bool valid;
61
+ DTEntry dte;
62
63
devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
64
- size = cmdpkt[1] & SIZE_MASK;
65
- itt_addr = (cmdpkt[2] & ITTADDR_MASK) >> ITTADDR_SHIFT;
66
- valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
67
+ dte.size = cmdpkt[1] & SIZE_MASK;
68
+ dte.ittaddr = (cmdpkt[2] & ITTADDR_MASK) >> ITTADDR_SHIFT;
69
+ dte.valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
70
71
if ((devid >= s->dt.num_entries) ||
72
- (size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
73
+ (dte.size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
74
qemu_log_mask(LOG_GUEST_ERROR,
75
"ITS MAPD: invalid device table attributes "
76
- "devid %d or size %d\n", devid, size);
77
+ "devid %d or size %d\n", devid, dte.size);
78
/*
79
* in this implementation, in case of error
80
* we ignore this command and move onto the next
81
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapd(GICv3ITSState *s, const uint64_t *cmdpkt)
82
return CMD_CONTINUE;
83
}
84
85
- return update_dte(s, devid, valid, size, itt_addr) ? CMD_CONTINUE : CMD_STALL;
86
+ return update_dte(s, devid, &dte) ? CMD_CONTINUE : CMD_STALL;
87
}
88
89
static ItsCmdResult process_movall(GICv3ITSState *s, const uint64_t *cmdpkt)
90
--
132
--
91
2.25.1
133
2.17.1
92
134
93
135
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Julia Suvorova <jusual@mail.ru>
2
2
3
When HCR_EL2.E2H is set, the format of CPTR_EL2 changes to
3
This feature is intended to distinguish ARMv8-M variants: Baseline and
4
look more like CPACR_EL1, with ZEN and FPEN fields instead
4
Mainline. ARMv7-M compatibility requires the Main Extension. ARMv6-M
5
of TZ and TFP fields.
5
compatibility is provided by all ARMv8-M implementations.
6
6
7
Reported-by: Zenghui Yu <yuzenghui@huawei.com>
7
Signed-off-by: Julia Suvorova <jusual@mail.ru>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180622080138.17702-2-jusual@mail.ru
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20220127063428.30212-4-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
11
---
13
target/arm/helper.c | 77 +++++++++++++++++++++++++++++++++++----------
12
target/arm/cpu.h | 1 +
14
1 file changed, 60 insertions(+), 17 deletions(-)
13
target/arm/cpu.c | 3 +++
14
2 files changed, 4 insertions(+)
15
15
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
18
--- a/target/arm/cpu.h
19
+++ b/target/arm/helper.c
19
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ int sve_exception_el(CPUARMState *env, int el)
20
@@ -XXX,XX +XXX,XX @@ enum arm_features {
21
}
21
ARM_FEATURE_V8_RDM, /* implements v8.1 simd round multiply */
22
}
22
ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
23
23
ARM_FEATURE_V8_FCMA, /* has complex number part of v8.3 extensions. */
24
- /* CPTR_EL2. Since TZ and TFP are positive,
24
+ ARM_FEATURE_M_MAIN, /* M profile Main Extension */
25
- * they will be zero when EL2 is not present.
25
};
26
+ /*
26
27
+ * CPTR_EL2 changes format with HCR_EL2.E2H (regardless of TGE).
27
static inline int arm_feature(CPUARMState *env, int feature)
28
*/
28
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
29
- if (el <= 2 && arm_is_el2_enabled(env)) {
29
index XXXXXXX..XXXXXXX 100644
30
- if (env->cp15.cptr_el[2] & CPTR_TZ) {
30
--- a/target/arm/cpu.c
31
- return 2;
31
+++ b/target/arm/cpu.c
32
- }
32
@@ -XXX,XX +XXX,XX @@ static void cortex_m3_initfn(Object *obj)
33
- if (env->cp15.cptr_el[2] & CPTR_TFP) {
33
ARMCPU *cpu = ARM_CPU(obj);
34
- return 0;
34
set_feature(&cpu->env, ARM_FEATURE_V7);
35
+ if (el <= 2) {
35
set_feature(&cpu->env, ARM_FEATURE_M);
36
+ if (hcr_el2 & HCR_E2H) {
36
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
37
+ /* Check CPTR_EL2.ZEN. */
37
cpu->midr = 0x410fc231;
38
+ switch (extract32(env->cp15.cptr_el[2], 16, 2)) {
38
cpu->pmsav7_dregion = 8;
39
+ case 1:
39
cpu->id_pfr0 = 0x00000030;
40
+ if (el != 0 || !(hcr_el2 & HCR_TGE)) {
40
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
41
+ break;
41
42
+ }
42
set_feature(&cpu->env, ARM_FEATURE_V7);
43
+ /* fall through */
43
set_feature(&cpu->env, ARM_FEATURE_M);
44
+ case 0:
44
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
45
+ case 2:
45
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
46
+ return 2;
46
cpu->midr = 0x410fc240; /* r0p0 */
47
+ }
47
cpu->pmsav7_dregion = 8;
48
+
48
@@ -XXX,XX +XXX,XX @@ static void cortex_m33_initfn(Object *obj)
49
+ /* Check CPTR_EL2.FPEN. */
49
50
+ switch (extract32(env->cp15.cptr_el[2], 20, 2)) {
50
set_feature(&cpu->env, ARM_FEATURE_V8);
51
+ case 1:
51
set_feature(&cpu->env, ARM_FEATURE_M);
52
+ if (el == 2 || !(hcr_el2 & HCR_TGE)) {
52
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
53
+ break;
53
set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
54
+ }
54
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
55
+ /* fall through */
55
cpu->midr = 0x410fd213; /* r0p3 */
56
+ case 0:
57
+ case 2:
58
+ return 0;
59
+ }
60
+ } else if (arm_is_el2_enabled(env)) {
61
+ if (env->cp15.cptr_el[2] & CPTR_TZ) {
62
+ return 2;
63
+ }
64
+ if (env->cp15.cptr_el[2] & CPTR_TFP) {
65
+ return 0;
66
+ }
67
}
68
}
69
70
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
71
int fp_exception_el(CPUARMState *env, int cur_el)
72
{
73
#ifndef CONFIG_USER_ONLY
74
+ uint64_t hcr_el2;
75
+
76
/* CPACR and the CPTR registers don't exist before v6, so FP is
77
* always accessible
78
*/
79
@@ -XXX,XX +XXX,XX @@ int fp_exception_el(CPUARMState *env, int cur_el)
80
return 0;
81
}
82
83
+ hcr_el2 = arm_hcr_el2_eff(env);
84
+
85
/* The CPACR controls traps to EL1, or PL1 if we're 32 bit:
86
* 0, 2 : trap EL0 and EL1/PL1 accesses
87
* 1 : trap only EL0 accesses
88
* 3 : trap no accesses
89
* This register is ignored if E2H+TGE are both set.
90
*/
91
- if ((arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
92
+ if ((hcr_el2 & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
93
int fpen = extract32(env->cp15.cpacr_el1, 20, 2);
94
95
switch (fpen) {
96
@@ -XXX,XX +XXX,XX @@ int fp_exception_el(CPUARMState *env, int cur_el)
97
}
98
}
99
100
- /* For the CPTR registers we don't need to guard with an ARM_FEATURE
101
- * check because zero bits in the registers mean "don't trap".
102
+ /*
103
+ * CPTR_EL2 is present in v7VE or v8, and changes format
104
+ * with HCR_EL2.E2H (regardless of TGE).
105
*/
106
-
107
- /* CPTR_EL2 : present in v7VE or v8 */
108
- if (cur_el <= 2 && extract32(env->cp15.cptr_el[2], 10, 1)
109
- && arm_is_el2_enabled(env)) {
110
- /* Trap FP ops at EL2, NS-EL1 or NS-EL0 to EL2 */
111
- return 2;
112
+ if (cur_el <= 2) {
113
+ if (hcr_el2 & HCR_E2H) {
114
+ /* Check CPTR_EL2.FPEN. */
115
+ switch (extract32(env->cp15.cptr_el[2], 20, 2)) {
116
+ case 1:
117
+ if (cur_el != 0 || !(hcr_el2 & HCR_TGE)) {
118
+ break;
119
+ }
120
+ /* fall through */
121
+ case 0:
122
+ case 2:
123
+ return 2;
124
+ }
125
+ } else if (arm_is_el2_enabled(env)) {
126
+ if (env->cp15.cptr_el[2] & CPTR_TFP) {
127
+ return 2;
128
+ }
129
+ }
130
}
131
132
/* CPTR_EL3 : present in v8 */
133
--
56
--
134
2.25.1
57
2.17.1
135
58
136
59
diff view generated by jsdifflib
Deleted patch
1
Change the allwinner-h3 based board to use the new boot.c
2
functionality to allow us to enable psci-conduit only if the guest is
3
being booted in EL1 or EL2, so that if the user runs guest EL3
4
firmware code our PSCI emulation doesn't get in its way.
5
1
6
To do this we stop setting the psci-conduit property on the CPU
7
objects in the SoC code, and instead set the psci_conduit field in
8
the arm_boot_info struct to tell the common boot loader code that
9
we'd like PSCI if the guest is starting at an EL that it makes sense
10
with.
11
12
This affects the orangepi-pc board.
13
14
This commit leaves the secondary CPUs in the powered-down state if
15
the guest is booting at EL3, which is the same behaviour as before
16
this commit. The secondaries can no longer be started by that EL3
17
code making a PSCI call but can still be started via the CPU
18
Configuration Module registers (which we model in
19
hw/misc/allwinner-cpucfg.c).
20
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
24
Tested-by: Cédric Le Goater <clg@kaod.org>
25
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
26
Message-id: 20220127154639.2090164-6-peter.maydell@linaro.org
27
---
28
hw/arm/allwinner-h3.c | 9 ++++-----
29
hw/arm/orangepi.c | 1 +
30
2 files changed, 5 insertions(+), 5 deletions(-)
31
32
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/allwinner-h3.c
35
+++ b/hw/arm/allwinner-h3.c
36
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
37
/* CPUs */
38
for (i = 0; i < AW_H3_NUM_CPUS; i++) {
39
40
- /* Provide Power State Coordination Interface */
41
- qdev_prop_set_int32(DEVICE(&s->cpus[i]), "psci-conduit",
42
- QEMU_PSCI_CONDUIT_SMC);
43
-
44
- /* Disable secondary CPUs */
45
+ /*
46
+ * Disable secondary CPUs. Guest EL3 firmware will start
47
+ * them via CPU reset control registers.
48
+ */
49
qdev_prop_set_bit(DEVICE(&s->cpus[i]), "start-powered-off",
50
i > 0);
51
52
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/hw/arm/orangepi.c
55
+++ b/hw/arm/orangepi.c
56
@@ -XXX,XX +XXX,XX @@ static void orangepi_init(MachineState *machine)
57
}
58
orangepi_binfo.loader_start = h3->memmap[AW_H3_DEV_SDRAM];
59
orangepi_binfo.ram_size = machine->ram_size;
60
+ orangepi_binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
61
arm_load_kernel(ARM_CPU(first_cpu), machine, &orangepi_binfo);
62
}
63
64
--
65
2.25.1
66
67
diff view generated by jsdifflib
Deleted patch
1
Guest code on highbank may make non-PSCI SMC calls in order to
2
enable/disable the L2x0 cache controller (see the Linux kernel's
3
arch/arm/mach-highbank/highbank.c highbank_l2c310_write_sec()
4
function). The ABI for this is documented in kernel commit
5
8e56130dcb as being borrowed from the OMAP44xx ROM. The OMAP44xx TRM
6
documents this function ID as having no return value and potentially
7
trashing all guest registers except SP and PC. For QEMU's purposes
8
(where our L2x0 model is a stub and enabling or disabling it doesn't
9
affect the guest behaviour) a simple "do nothing" SMC is fine.
10
1
11
We currently implement this NOP behaviour using a little bit of
12
Secure code we run before jumping to the guest kernel, which is
13
written by arm_write_secure_board_setup_dummy_smc(). The code sets
14
up a set of Secure vectors where the SMC entry point returns without
15
doing anything.
16
17
Now that the PSCI SMC emulation handles all SMC calls (setting r0 to
18
an error code if the input r0 function identifier is not recognized),
19
we can use that default behaviour as sufficient for the highbank
20
cache controller call. (Because the guest code assumes r0 has no
21
interesting value on exit it doesn't matter that we set it to the
22
error code). We can therefore delete the highbank board code that
23
sets secure_board_setup to true and writes the secure-code bootstub.
24
25
(Note that because the OMAP44xx ABI puts function-identifiers in
26
r12 and PSCI uses r0, we only avoid a clash because Linux's code
27
happens to put the function-identifier in both registers. But this
28
is true also when the kernel is running on real firmware that
29
implements both ABIs as far as I can see.)
30
31
This change fixes in passing booting on the 'midway' board model,
32
which has been completely broken since we added support for Hyp
33
mode to the Cortex-A15 CPU. When we did that boot.c was made to
34
start running the guest code in Hyp mode; this includes the
35
board_setup hook, which instantly UNDEFs because the NSACR is
36
not accessible from Hyp. (Put another way, we never made the
37
secure_board_setup hook support cope with Hyp mode.)
38
39
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
40
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
41
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
42
Tested-by: Cédric Le Goater <clg@kaod.org>
43
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
44
Message-id: 20220127154639.2090164-12-peter.maydell@linaro.org
45
---
46
hw/arm/highbank.c | 8 --------
47
1 file changed, 8 deletions(-)
48
49
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/highbank.c
52
+++ b/hw/arm/highbank.c
53
@@ -XXX,XX +XXX,XX @@
54
55
/* Board init. */
56
57
-static void hb_write_board_setup(ARMCPU *cpu,
58
- const struct arm_boot_info *info)
59
-{
60
- arm_write_secure_board_setup_dummy_smc(cpu, info, MVBAR_ADDR);
61
-}
62
-
63
static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
64
{
65
int n;
66
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
67
highbank_binfo.write_secondary_boot = hb_write_secondary;
68
highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
69
highbank_binfo.board_setup_addr = BOARD_SETUP_ADDR;
70
- highbank_binfo.write_board_setup = hb_write_board_setup;
71
- highbank_binfo.secure_board_setup = true;
72
highbank_binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
73
74
arm_load_kernel(ARM_CPU(first_cpu), machine, &highbank_binfo);
75
--
76
2.25.1
77
78
diff view generated by jsdifflib
Deleted patch
1
Now that we have dealt with the one special case (highbank) that needed
2
to set both psci_conduit and secure_board_setup, we don't need to
3
allow that combination any more. It doesn't make sense in general,
4
so use an assertion to ensure we don't add new boards that do it
5
by accident without thinking through the consequences.
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
10
Tested-by: Cédric Le Goater <clg@kaod.org>
11
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
12
Message-id: 20220127154639.2090164-13-peter.maydell@linaro.org
13
---
14
hw/arm/boot.c | 10 ++++++++++
15
1 file changed, 10 insertions(+)
16
17
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/boot.c
20
+++ b/hw/arm/boot.c
21
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
22
* supported exception level or in a lower one.
23
*/
24
25
+ /*
26
+ * If PSCI is enabled, then SMC calls all go to the PSCI handler and
27
+ * are never emulated to trap into guest code. It therefore does not
28
+ * make sense for the board to have a setup code fragment that runs
29
+ * in Secure, because this will probably need to itself issue an SMC of some
30
+ * kind as part of its operation.
31
+ */
32
+ assert(info->psci_conduit == QEMU_PSCI_CONDUIT_DISABLED ||
33
+ !info->secure_board_setup);
34
+
35
/* Boot into highest supported EL ... */
36
if (arm_feature(env, ARM_FEATURE_EL3)) {
37
boot_el = 3;
38
--
39
2.25.1
40
41
diff view generated by jsdifflib
Deleted patch
1
If we're using PSCI emulation to start secondary CPUs, there is no
2
point in writing the "secondary boot" stub code, because it will
3
never be used -- secondary CPUs start powered-off, and when powered
4
on are set to begin execution at the address specified by the guest's
5
power-on PSCI call, not at the stub.
6
1
7
Move the call to the hook that writes the secondary boot stub code so
8
that we can do it only if we're starting a Linux kernel and not using
9
PSCI.
10
11
(None of the users of the hook care about the ordering of its call
12
relative to anything else: they only use it to write a rom blob to
13
guest memory.)
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
18
Tested-by: Cédric Le Goater <clg@kaod.org>
19
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
20
Message-id: 20220127154639.2090164-14-peter.maydell@linaro.org
21
---
22
include/hw/arm/boot.h | 3 +++
23
hw/arm/boot.c | 35 ++++++++++++++++++++++++-----------
24
2 files changed, 27 insertions(+), 11 deletions(-)
25
26
diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/include/hw/arm/boot.h
29
+++ b/include/hw/arm/boot.h
30
@@ -XXX,XX +XXX,XX @@ struct arm_boot_info {
31
* boot loader/boot ROM code, and secondary_cpu_reset_hook() should
32
* perform any necessary CPU reset handling and set the PC for the
33
* secondary CPUs to point at this boot blob.
34
+ *
35
+ * These hooks won't be called if secondary CPUs are booting via
36
+ * emulated PSCI (see psci_conduit below).
37
*/
38
void (*write_secondary_boot)(ARMCPU *cpu,
39
const struct arm_boot_info *info);
40
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/arm/boot.c
43
+++ b/hw/arm/boot.c
44
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
45
set_kernel_args(info, as);
46
}
47
}
48
- } else {
49
+ } else if (info->secondary_cpu_reset_hook) {
50
info->secondary_cpu_reset_hook(cpu, info);
51
}
52
}
53
@@ -XXX,XX +XXX,XX @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
54
elf_machine = EM_ARM;
55
}
56
57
- if (!info->secondary_cpu_reset_hook) {
58
- info->secondary_cpu_reset_hook = default_reset_secondary;
59
- }
60
- if (!info->write_secondary_boot) {
61
- info->write_secondary_boot = default_write_secondary;
62
- }
63
-
64
if (info->nb_cpus == 0)
65
info->nb_cpus = 1;
66
67
@@ -XXX,XX +XXX,XX @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
68
write_bootloader("bootloader", info->loader_start,
69
primary_loader, fixupcontext, as);
70
71
- if (info->nb_cpus > 1) {
72
- info->write_secondary_boot(cpu, info);
73
- }
74
if (info->write_board_setup) {
75
info->write_board_setup(cpu, info);
76
}
77
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
78
}
79
}
80
81
+ if (info->psci_conduit == QEMU_PSCI_CONDUIT_DISABLED &&
82
+ info->is_linux && info->nb_cpus > 1) {
83
+ /*
84
+ * We're booting Linux but not using PSCI, so for SMP we need
85
+ * to write a custom secondary CPU boot loader stub, and arrange
86
+ * for the secondary CPU reset to make the accompanying initialization.
87
+ */
88
+ if (!info->secondary_cpu_reset_hook) {
89
+ info->secondary_cpu_reset_hook = default_reset_secondary;
90
+ }
91
+ if (!info->write_secondary_boot) {
92
+ info->write_secondary_boot = default_write_secondary;
93
+ }
94
+ info->write_secondary_boot(cpu, info);
95
+ } else {
96
+ /*
97
+ * No secondary boot stub; don't use the reset hook that would
98
+ * have set the CPU up to call it
99
+ */
100
+ info->write_secondary_boot = NULL;
101
+ info->secondary_cpu_reset_hook = NULL;
102
+ }
103
+
104
/*
105
* arm_load_dtb() may add a PSCI node so it must be called after we have
106
* decided whether to enable PSCI and set the psci-conduit CPU properties.
107
--
108
2.25.1
109
110
diff view generated by jsdifflib
Deleted patch
1
The highbank and midway board code includes boot-stub code for
2
handling secondary CPU boot which keeps the secondaries in a pen
3
until the primary writes to a known location with the address they
4
should jump to.
5
1
6
This code is never used, because the boards enable QEMU's PSCI
7
emulation, so secondary CPUs are kept powered off until the PSCI call
8
which turns them on, and then start execution from the address given
9
by the guest in that PSCI call. Delete the unreachable code.
10
11
(The code was wrong for midway in any case -- on the Cortex-A15 the
12
GIC CPU interface registers are at a different offset from PERIPHBASE
13
compared to the Cortex-A9, and the code baked-in the offsets for
14
highbank's A9.)
15
16
Note that this commit implicitly depends on the preceding "Don't
17
write secondary boot stub if using PSCI" commit -- the default
18
secondary-boot stub code overlaps with one of the highbank-specific
19
bootcode rom blobs, so we must suppress the secondary-boot
20
stub code entirely, not merely replace the highbank-specific
21
version with the default.
22
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
26
Tested-by: Cédric Le Goater <clg@kaod.org>
27
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
28
Message-id: 20220127154639.2090164-15-peter.maydell@linaro.org
29
---
30
hw/arm/highbank.c | 56 -----------------------------------------------
31
1 file changed, 56 deletions(-)
32
33
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/highbank.c
36
+++ b/hw/arm/highbank.c
37
@@ -XXX,XX +XXX,XX @@
38
39
/* Board init. */
40
41
-static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
42
-{
43
- int n;
44
- uint32_t smpboot[] = {
45
- 0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 - read current core id */
46
- 0xe210000f, /* ands r0, r0, #0x0f */
47
- 0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */
48
- 0xe0830200, /* add r0, r3, r0, lsl #4 */
49
- 0xe59f2024, /* ldr r2, privbase */
50
- 0xe3a01001, /* mov r1, #1 */
51
- 0xe5821100, /* str r1, [r2, #256] - set GICC_CTLR.Enable */
52
- 0xe3a010ff, /* mov r1, #0xff */
53
- 0xe5821104, /* str r1, [r2, #260] - set GICC_PMR.Priority to 0xff */
54
- 0xf57ff04f, /* dsb */
55
- 0xe320f003, /* wfi */
56
- 0xe5901000, /* ldr r1, [r0] */
57
- 0xe1110001, /* tst r1, r1 */
58
- 0x0afffffb, /* beq <wfi> */
59
- 0xe12fff11, /* bx r1 */
60
- MPCORE_PERIPHBASE /* privbase: MPCore peripheral base address. */
61
- };
62
- for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
63
- smpboot[n] = tswap32(smpboot[n]);
64
- }
65
- rom_add_blob_fixed_as("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR,
66
- arm_boot_address_space(cpu, info));
67
-}
68
-
69
-static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
70
-{
71
- CPUARMState *env = &cpu->env;
72
-
73
- switch (info->nb_cpus) {
74
- case 4:
75
- address_space_stl_notdirty(&address_space_memory,
76
- SMP_BOOT_REG + 0x30, 0,
77
- MEMTXATTRS_UNSPECIFIED, NULL);
78
- /* fallthrough */
79
- case 3:
80
- address_space_stl_notdirty(&address_space_memory,
81
- SMP_BOOT_REG + 0x20, 0,
82
- MEMTXATTRS_UNSPECIFIED, NULL);
83
- /* fallthrough */
84
- case 2:
85
- address_space_stl_notdirty(&address_space_memory,
86
- SMP_BOOT_REG + 0x10, 0,
87
- MEMTXATTRS_UNSPECIFIED, NULL);
88
- env->regs[15] = SMP_BOOT_ADDR;
89
- break;
90
- default:
91
- break;
92
- }
93
-}
94
-
95
#define NUM_REGS 0x200
96
static void hb_regs_write(void *opaque, hwaddr offset,
97
uint64_t value, unsigned size)
98
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
99
highbank_binfo.board_id = -1;
100
highbank_binfo.nb_cpus = smp_cpus;
101
highbank_binfo.loader_start = 0;
102
- highbank_binfo.write_secondary_boot = hb_write_secondary;
103
- highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
104
highbank_binfo.board_setup_addr = BOARD_SETUP_ADDR;
105
highbank_binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
106
107
--
108
2.25.1
109
110
diff view generated by jsdifflib
Deleted patch
1
If we're using PSCI emulation, we add a /psci node to the device tree
2
we pass to the guest. At the moment, if the dtb already has a /psci
3
node in it, we retain it, rather than replacing it. (This behaviour
4
was added in commit c39770cd637765 in 2018.)
5
1
6
This is a problem if the existing node doesn't match our PSCI
7
emulation. In particular, it might specify the wrong method (HVC vs
8
SMC), or wrong function IDs for cpu_suspend/cpu_off/etc, in which
9
case the guest will not get the behaviour it wants when it makes PSCI
10
calls.
11
12
An example of this is trying to boot the highbank or midway board
13
models using the device tree supplied in the kernel sources: this
14
device tree includes a /psci node that specifies function IDs that
15
don't match the (PSCI 0.2 compliant) IDs that QEMU uses. The dtb
16
cpu_suspend function ID happens to match the PSCI 0.2 cpu_off ID, so
17
the guest hangs after booting when the kernel tries to idle the CPU
18
and instead it gets turned off.
19
20
Instead of retaining an existing /psci node, delete it entirely
21
and replace it with a node whose properties match QEMU's PSCI
22
emulation behaviour. This matches the way we handle /memory nodes,
23
where we also delete any existing nodes and write in ones that
24
match the way QEMU is going to behave.
25
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
28
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
29
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
30
Tested-by: Cédric Le Goater <clg@kaod.org>
31
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
32
Message-id: 20220127154639.2090164-17-peter.maydell@linaro.org
33
---
34
hw/arm/boot.c | 7 ++++---
35
1 file changed, 4 insertions(+), 3 deletions(-)
36
37
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/arm/boot.c
40
+++ b/hw/arm/boot.c
41
@@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt)
42
}
43
44
/*
45
- * If /psci node is present in provided DTB, assume that no fixup
46
- * is necessary and all PSCI configuration should be taken as-is
47
+ * A pre-existing /psci node might specify function ID values
48
+ * that don't match QEMU's PSCI implementation. Delete the whole
49
+ * node and put our own in instead.
50
*/
51
rc = fdt_path_offset(fdt, "/psci");
52
if (rc >= 0) {
53
- return;
54
+ qemu_fdt_nop_node(fdt, "/psci");
55
}
56
57
qemu_fdt_add_subnode(fdt, "/psci");
58
--
59
2.25.1
60
61
diff view generated by jsdifflib
Deleted patch
1
In the ITS, a DTE is an entry in the device table, which contains
2
multiple fields. Currently the function get_dte() which reads one
3
entry from the device table returns it as a raw 64-bit integer,
4
which we then pass around in that form, only extracting fields
5
from it as we need them.
6
1
7
Create a real C struct with the same fields as the DTE, and
8
populate it in get_dte(), so that that function and update_dte()
9
are the only ones that need to care about the in-guest-memory
10
format of the DTE.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20220201193207.2771604-3-peter.maydell@linaro.org
15
---
16
hw/intc/arm_gicv3_its.c | 111 ++++++++++++++++++++--------------------
17
1 file changed, 56 insertions(+), 55 deletions(-)
18
19
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/intc/arm_gicv3_its.c
22
+++ b/hw/intc/arm_gicv3_its.c
23
@@ -XXX,XX +XXX,XX @@ typedef struct {
24
uint64_t itel;
25
} IteEntry;
26
27
+typedef struct DTEntry {
28
+ bool valid;
29
+ unsigned size;
30
+ uint64_t ittaddr;
31
+} DTEntry;
32
+
33
/*
34
* The ITS spec permits a range of CONSTRAINED UNPREDICTABLE options
35
* if a command parameter is not correct. These include both "stall
36
@@ -XXX,XX +XXX,XX @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
37
return FIELD_EX64(*cte, CTE, VALID);
38
}
39
40
-static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
41
+static bool update_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
42
IteEntry ite)
43
{
44
AddressSpace *as = &s->gicv3->dma_as;
45
- uint64_t itt_addr;
46
MemTxResult res = MEMTX_OK;
47
48
- itt_addr = FIELD_EX64(dte, DTE, ITTADDR);
49
- itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
50
-
51
- address_space_stq_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
52
+ address_space_stq_le(as, dte->ittaddr + (eventid * (sizeof(uint64_t) +
53
sizeof(uint32_t))), ite.itel, MEMTXATTRS_UNSPECIFIED,
54
&res);
55
56
if (res == MEMTX_OK) {
57
- address_space_stl_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
58
+ address_space_stl_le(as, dte->ittaddr + (eventid * (sizeof(uint64_t) +
59
sizeof(uint32_t))) + sizeof(uint32_t), ite.iteh,
60
MEMTXATTRS_UNSPECIFIED, &res);
61
}
62
@@ -XXX,XX +XXX,XX @@ static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
63
}
64
}
65
66
-static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
67
+static bool get_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
68
uint16_t *icid, uint32_t *pIntid, MemTxResult *res)
69
{
70
AddressSpace *as = &s->gicv3->dma_as;
71
- uint64_t itt_addr;
72
bool status = false;
73
IteEntry ite = {};
74
75
- itt_addr = FIELD_EX64(dte, DTE, ITTADDR);
76
- itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
77
-
78
- ite.itel = address_space_ldq_le(as, itt_addr +
79
+ ite.itel = address_space_ldq_le(as, dte->ittaddr +
80
(eventid * (sizeof(uint64_t) +
81
sizeof(uint32_t))), MEMTXATTRS_UNSPECIFIED,
82
res);
83
84
if (*res == MEMTX_OK) {
85
- ite.iteh = address_space_ldl_le(as, itt_addr +
86
+ ite.iteh = address_space_ldl_le(as, dte->ittaddr +
87
(eventid * (sizeof(uint64_t) +
88
sizeof(uint32_t))) + sizeof(uint32_t),
89
MEMTXATTRS_UNSPECIFIED, res);
90
@@ -XXX,XX +XXX,XX @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
91
return status;
92
}
93
94
-static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
95
+/*
96
+ * Read the Device Table entry at index @devid. On success (including
97
+ * successfully determining that there is no valid DTE for this index),
98
+ * we return MEMTX_OK and populate the DTEntry struct accordingly.
99
+ * If there is an error reading memory then we return the error code.
100
+ */
101
+static MemTxResult get_dte(GICv3ITSState *s, uint32_t devid, DTEntry *dte)
102
{
103
+ MemTxResult res = MEMTX_OK;
104
AddressSpace *as = &s->gicv3->dma_as;
105
- uint64_t entry_addr = table_entry_addr(s, &s->dt, devid, res);
106
+ uint64_t entry_addr = table_entry_addr(s, &s->dt, devid, &res);
107
+ uint64_t dteval;
108
109
if (entry_addr == -1) {
110
- return 0; /* a DTE entry with the Valid bit clear */
111
+ /* No L2 table entry, i.e. no valid DTE, or a memory error */
112
+ dte->valid = false;
113
+ return res;
114
}
115
- return address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, res);
116
+ dteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res);
117
+ if (res != MEMTX_OK) {
118
+ return res;
119
+ }
120
+ dte->valid = FIELD_EX64(dteval, DTE, VALID);
121
+ dte->size = FIELD_EX64(dteval, DTE, SIZE);
122
+ /* DTE word field stores bits [51:8] of the ITT address */
123
+ dte->ittaddr = FIELD_EX64(dteval, DTE, ITTADDR) << ITTADDR_SHIFT;
124
+ return MEMTX_OK;
125
}
126
127
/*
128
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
129
uint32_t eventid, ItsCmdType cmd)
130
{
131
MemTxResult res = MEMTX_OK;
132
- bool dte_valid;
133
- uint64_t dte = 0;
134
uint64_t num_eventids;
135
uint16_t icid = 0;
136
uint32_t pIntid = 0;
137
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
138
uint64_t cte = 0;
139
bool cte_valid = false;
140
uint64_t rdbase;
141
+ DTEntry dte;
142
143
if (devid >= s->dt.num_entries) {
144
qemu_log_mask(LOG_GUEST_ERROR,
145
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
146
return CMD_CONTINUE;
147
}
148
149
- dte = get_dte(s, devid, &res);
150
-
151
- if (res != MEMTX_OK) {
152
+ if (get_dte(s, devid, &dte) != MEMTX_OK) {
153
return CMD_STALL;
154
}
155
- dte_valid = FIELD_EX64(dte, DTE, VALID);
156
-
157
- if (!dte_valid) {
158
+ if (!dte.valid) {
159
qemu_log_mask(LOG_GUEST_ERROR,
160
"%s: invalid command attributes: "
161
- "invalid dte: %"PRIx64" for %d\n",
162
- __func__, dte, devid);
163
+ "invalid dte for %d\n", __func__, devid);
164
return CMD_CONTINUE;
165
}
166
167
- num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
168
-
169
+ num_eventids = 1ULL << (dte.size + 1);
170
if (eventid >= num_eventids) {
171
qemu_log_mask(LOG_GUEST_ERROR,
172
"%s: invalid command attributes: eventid %d >= %"
173
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
174
return CMD_CONTINUE;
175
}
176
177
- ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res);
178
+ ite_valid = get_ite(s, eventid, &dte, &icid, &pIntid, &res);
179
if (res != MEMTX_OK) {
180
return CMD_STALL;
181
}
182
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
183
if (cmd == DISCARD) {
184
IteEntry ite = {};
185
/* remove mapping from interrupt translation table */
186
- return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL;
187
+ return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
188
}
189
return CMD_CONTINUE;
190
}
191
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
192
uint32_t pIntid = 0;
193
uint64_t num_eventids;
194
uint32_t num_intids;
195
- bool dte_valid;
196
- MemTxResult res = MEMTX_OK;
197
uint16_t icid = 0;
198
- uint64_t dte = 0;
199
IteEntry ite = {};
200
+ DTEntry dte;
201
202
devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
203
eventid = cmdpkt[1] & EVENTID_MASK;
204
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
205
return CMD_CONTINUE;
206
}
207
208
- dte = get_dte(s, devid, &res);
209
-
210
- if (res != MEMTX_OK) {
211
+ if (get_dte(s, devid, &dte) != MEMTX_OK) {
212
return CMD_STALL;
213
}
214
- dte_valid = FIELD_EX64(dte, DTE, VALID);
215
- num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
216
+ num_eventids = 1ULL << (dte.size + 1);
217
num_intids = 1ULL << (GICD_TYPER_IDBITS + 1);
218
219
if ((icid >= s->ct.num_entries)
220
- || !dte_valid || (eventid >= num_eventids) ||
221
+ || !dte.valid || (eventid >= num_eventids) ||
222
(((pIntid < GICV3_LPI_INTID_START) || (pIntid >= num_intids)) &&
223
(pIntid != INTID_SPURIOUS))) {
224
qemu_log_mask(LOG_GUEST_ERROR,
225
"%s: invalid command attributes "
226
"icid %d or eventid %d or pIntid %d or"
227
"unmapped dte %d\n", __func__, icid, eventid,
228
- pIntid, dte_valid);
229
+ pIntid, dte.valid);
230
/*
231
* in this implementation, in case of error
232
* we ignore this command and move onto the next
233
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
234
}
235
236
/* add ite entry to interrupt translation table */
237
- ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, dte_valid);
238
+ ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, true);
239
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
240
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid);
241
ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
242
ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid);
243
244
- return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL;
245
+ return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
246
}
247
248
static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
249
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
250
uint16_t old_icid, new_icid;
251
uint64_t old_cte, new_cte;
252
uint64_t old_rdbase, new_rdbase;
253
- uint64_t dte;
254
- bool dte_valid, ite_valid, cte_valid;
255
+ bool ite_valid, cte_valid;
256
uint64_t num_eventids;
257
IteEntry ite = {};
258
+ DTEntry dte;
259
260
devid = FIELD_EX64(cmdpkt[0], MOVI_0, DEVICEID);
261
eventid = FIELD_EX64(cmdpkt[1], MOVI_1, EVENTID);
262
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
263
__func__, devid, s->dt.num_entries);
264
return CMD_CONTINUE;
265
}
266
- dte = get_dte(s, devid, &res);
267
- if (res != MEMTX_OK) {
268
+ if (get_dte(s, devid, &dte) != MEMTX_OK) {
269
return CMD_STALL;
270
}
271
272
- dte_valid = FIELD_EX64(dte, DTE, VALID);
273
- if (!dte_valid) {
274
+ if (!dte.valid) {
275
qemu_log_mask(LOG_GUEST_ERROR,
276
"%s: invalid command attributes: "
277
- "invalid dte: %"PRIx64" for %d\n",
278
- __func__, dte, devid);
279
+ "invalid dte for %d\n", __func__, devid);
280
return CMD_CONTINUE;
281
}
282
283
- num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
284
+ num_eventids = 1ULL << (dte.size + 1);
285
if (eventid >= num_eventids) {
286
qemu_log_mask(LOG_GUEST_ERROR,
287
"%s: invalid command attributes: eventid %d >= %"
288
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
289
return CMD_CONTINUE;
290
}
291
292
- ite_valid = get_ite(s, eventid, dte, &old_icid, &intid, &res);
293
+ ite_valid = get_ite(s, eventid, &dte, &old_icid, &intid, &res);
294
if (res != MEMTX_OK) {
295
return CMD_STALL;
296
}
297
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
298
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, intid);
299
ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
300
ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, new_icid);
301
- return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL;
302
+ return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
303
}
304
305
/*
306
--
307
2.25.1
308
309
diff view generated by jsdifflib
1
In most of the ITS command processing, we check different error
1
From: Julia Suvorova <jusual@mail.ru>
2
possibilities one at a time and log them appropriately. In
3
process_mapti() and process_mapd() we have code which checks
4
multiple error cases at once, which means the logging is less
5
specific than it could be. Split those cases up.
6
2
3
Unlike ARMv7-M, ARMv6-M and ARMv8-M Baseline only supports naturally
4
aligned memory accesses for load/store instructions.
5
6
Signed-off-by: Julia Suvorova <jusual@mail.ru>
7
Message-id: 20180622080138.17702-3-jusual@mail.ru
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: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220201193207.2771604-14-peter.maydell@linaro.org
10
---
10
---
11
hw/intc/arm_gicv3_its.c | 52 ++++++++++++++++++++++++-----------------
11
target/arm/translate.c | 18 ++++++++++++++++--
12
1 file changed, 31 insertions(+), 21 deletions(-)
12
1 file changed, 16 insertions(+), 2 deletions(-)
13
13
14
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/arm_gicv3_its.c
16
--- a/target/arm/translate.c
17
+++ b/hw/intc/arm_gicv3_its.c
17
+++ b/target/arm/translate.c
18
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
18
@@ -XXX,XX +XXX,XX @@ static inline TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, TCGMemOp op)
19
num_eventids = 1ULL << (dte.size + 1);
19
static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
20
num_intids = 1ULL << (GICD_TYPER_IDBITS + 1);
20
int index, TCGMemOp opc)
21
21
{
22
- if ((icid >= s->ct.num_entries)
22
- TCGv addr = gen_aa32_addr(s, a32, opc);
23
- || !dte.valid || (eventid >= num_eventids) ||
23
+ TCGv addr;
24
- (((pIntid < GICV3_LPI_INTID_START) || (pIntid >= num_intids)))) {
24
+
25
+ if (icid >= s->ct.num_entries) {
25
+ if (arm_dc_feature(s, ARM_FEATURE_M) &&
26
qemu_log_mask(LOG_GUEST_ERROR,
26
+ !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
27
- "%s: invalid command attributes "
27
+ opc |= MO_ALIGN;
28
- "icid %d or eventid %d or pIntid %d or"
29
- "unmapped dte %d\n", __func__, icid, eventid,
30
- pIntid, dte.valid);
31
- /*
32
- * in this implementation, in case of error
33
- * we ignore this command and move onto the next
34
- * command in the queue
35
- */
36
+ "%s: invalid ICID 0x%x >= 0x%x\n",
37
+ __func__, icid, s->ct.num_entries);
38
+ return CMD_CONTINUE;
39
+ }
28
+ }
40
+
29
+
41
+ if (!dte.valid) {
30
+ addr = gen_aa32_addr(s, a32, opc);
42
+ qemu_log_mask(LOG_GUEST_ERROR,
31
tcg_gen_qemu_ld_i32(val, addr, index, opc);
43
+ "%s: no valid DTE for devid 0x%x\n", __func__, devid);
32
tcg_temp_free(addr);
44
+ return CMD_CONTINUE;
33
}
34
@@ -XXX,XX +XXX,XX @@ static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
35
static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
36
int index, TCGMemOp opc)
37
{
38
- TCGv addr = gen_aa32_addr(s, a32, opc);
39
+ TCGv addr;
40
+
41
+ if (arm_dc_feature(s, ARM_FEATURE_M) &&
42
+ !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
43
+ opc |= MO_ALIGN;
45
+ }
44
+ }
46
+
45
+
47
+ if (eventid >= num_eventids) {
46
+ addr = gen_aa32_addr(s, a32, opc);
48
+ qemu_log_mask(LOG_GUEST_ERROR,
47
tcg_gen_qemu_st_i32(val, addr, index, opc);
49
+ "%s: invalid event ID 0x%x >= 0x%" PRIx64 "\n",
48
tcg_temp_free(addr);
50
+ __func__, eventid, num_eventids);
49
}
51
+ return CMD_CONTINUE;
52
+ }
53
+
54
+ if (pIntid < GICV3_LPI_INTID_START || pIntid >= num_intids) {
55
+ qemu_log_mask(LOG_GUEST_ERROR,
56
+ "%s: invalid interrupt ID 0x%x\n", __func__, pIntid);
57
return CMD_CONTINUE;
58
}
59
60
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapd(GICv3ITSState *s, const uint64_t *cmdpkt)
61
dte.ittaddr = (cmdpkt[2] & ITTADDR_MASK) >> ITTADDR_SHIFT;
62
dte.valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
63
64
- if ((devid >= s->dt.num_entries) ||
65
- (dte.size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
66
+ if (devid >= s->dt.num_entries) {
67
qemu_log_mask(LOG_GUEST_ERROR,
68
- "ITS MAPD: invalid device table attributes "
69
- "devid %d or size %d\n", devid, dte.size);
70
- /*
71
- * in this implementation, in case of error
72
- * we ignore this command and move onto the next
73
- * command in the queue
74
- */
75
+ "ITS MAPD: invalid device ID field 0x%x >= 0x%x\n",
76
+ devid, s->dt.num_entries);
77
+ return CMD_CONTINUE;
78
+ }
79
+
80
+ if (dte.size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS)) {
81
+ qemu_log_mask(LOG_GUEST_ERROR,
82
+ "ITS MAPD: invalid size %d\n", dte.size);
83
return CMD_CONTINUE;
84
}
85
86
--
50
--
87
2.25.1
51
2.17.1
88
52
89
53
diff view generated by jsdifflib
1
When handling MAPI/MAPTI, we allow the supplied interrupt ID to be
1
checkpatch reminds us that statics shouldn't be zero-initialized:
2
either 1023 or something in the valid LPI range. This is a mistake:
2
3
only a real valid LPI is allowed. (The general behaviour of the ITS
3
ERROR: do not initialise statics to 0 or NULL
4
is that most interrupt ID fields require a value in the LPI range;
4
#35: FILE: vl.c:157:
5
the exception is that fields specifying a doorbell value, which are
5
+static int num_serial_hds = 0;
6
all in GICv4 commands, allow also 1023 to mean "no doorbell".)
6
7
Remove the condition that incorrectly allows 1023 here.
7
ERROR: do not initialise statics to 0 or NULL
8
#36: FILE: vl.c:158:
9
+static Chardev **serial_hds = NULL;
10
11
I forgot to fix this in 6af2692e86f9fdfb3d; do so now.
8
12
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Thomas Huth <thuth@redhat.com>
11
Message-id: 20220201193207.2771604-13-peter.maydell@linaro.org
15
Message-id: 20180426140253.3918-1-peter.maydell@linaro.org
12
---
16
---
13
hw/intc/arm_gicv3_its.c | 3 +--
17
vl.c | 4 ++--
14
1 file changed, 1 insertion(+), 2 deletions(-)
18
1 file changed, 2 insertions(+), 2 deletions(-)
15
19
16
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
20
diff --git a/vl.c b/vl.c
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/intc/arm_gicv3_its.c
22
--- a/vl.c
19
+++ b/hw/intc/arm_gicv3_its.c
23
+++ b/vl.c
20
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
24
@@ -XXX,XX +XXX,XX @@ QEMUClockType rtc_clock;
21
25
int vga_interface_type = VGA_NONE;
22
if ((icid >= s->ct.num_entries)
26
static DisplayOptions dpy;
23
|| !dte.valid || (eventid >= num_eventids) ||
27
int no_frame;
24
- (((pIntid < GICV3_LPI_INTID_START) || (pIntid >= num_intids)) &&
28
-static int num_serial_hds = 0;
25
- (pIntid != INTID_SPURIOUS))) {
29
-static Chardev **serial_hds = NULL;
26
+ (((pIntid < GICV3_LPI_INTID_START) || (pIntid >= num_intids)))) {
30
+static int num_serial_hds;
27
qemu_log_mask(LOG_GUEST_ERROR,
31
+static Chardev **serial_hds;
28
"%s: invalid command attributes "
32
Chardev *parallel_hds[MAX_PARALLEL_PORTS];
29
"icid %d or eventid %d or pIntid %d or"
33
Chardev *virtcon_hds[MAX_VIRTIO_CONSOLES];
34
int win2k_install_hack = 0;
30
--
35
--
31
2.25.1
36
2.17.1
32
37
33
38
diff view generated by jsdifflib
1
In the ITS, a CTE is an entry in the collection table, which contains
1
The xen pci_assign_dev_load_option_rom() currently creates a RAM
2
multiple fields. Currently the function get_cte() which reads one
2
memory region with memory_region_init_ram_nomigrate(), and then
3
entry from the device table returns a success/failure boolean and
3
manually registers it with vmstate_register_ram(). In fact for
4
passes back the raw 64-bit integer CTE value via a pointer argument.
4
its only callsite, the 'owner' pointer we use for the init call
5
We then extract fields from the CTE as we need them.
5
and the '&dev->qdev' pointer we use for the vmstate_register_ram()
6
call refer to the same object. Simplify the function to only
7
take a pointer to the device once instead of twice, and use
8
memory_region_init_ram() which automatically does the vmstate
9
register for us.
6
10
7
Create a real C struct with the same fields as the CTE, and
11
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
8
populate it in get_cte(), so that that function and update_cte()
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
are the only ones which need to care about the in-guest-memory
13
---
10
format of the CTE.
14
hw/xen/xen_pt.h | 2 +-
15
hw/xen/xen_pt_graphics.c | 2 +-
16
hw/xen/xen_pt_load_rom.c | 6 +++---
17
3 files changed, 5 insertions(+), 5 deletions(-)
11
18
12
This brings get_cte()'s API into line with get_dte().
19
diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20220201193207.2771604-5-peter.maydell@linaro.org
17
---
18
hw/intc/arm_gicv3_its.c | 96 ++++++++++++++++++++++-------------------
19
1 file changed, 52 insertions(+), 44 deletions(-)
20
21
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
22
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/intc/arm_gicv3_its.c
21
--- a/hw/xen/xen_pt.h
24
+++ b/hw/intc/arm_gicv3_its.c
22
+++ b/hw/xen/xen_pt.h
25
@@ -XXX,XX +XXX,XX @@ typedef struct DTEntry {
23
@@ -XXX,XX +XXX,XX @@ static inline bool xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar)
26
uint64_t ittaddr;
27
} DTEntry;
28
29
+typedef struct CTEntry {
30
+ bool valid;
31
+ uint32_t rdbase;
32
+} CTEntry;
33
+
34
/*
35
* The ITS spec permits a range of CONSTRAINED UNPREDICTABLE options
36
* if a command parameter is not correct. These include both "stall
37
@@ -XXX,XX +XXX,XX @@ static uint64_t table_entry_addr(GICv3ITSState *s, TableDesc *td,
38
return (l2 & ((1ULL << 51) - 1)) + (idx % num_l2_entries) * td->entry_sz;
39
}
24
}
40
25
41
-static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
26
extern void *pci_assign_dev_load_option_rom(PCIDevice *dev,
42
- MemTxResult *res)
27
- struct Object *owner, int *size,
43
+/*
28
+ int *size,
44
+ * Read the Collection Table entry at index @icid. On success (including
29
unsigned int domain,
45
+ * successfully determining that there is no valid CTE for this index),
30
unsigned int bus, unsigned int slot,
46
+ * we return MEMTX_OK and populate the CTEntry struct @cte accordingly.
31
unsigned int function);
47
+ * If there is an error reading memory then we return the error code.
32
diff --git a/hw/xen/xen_pt_graphics.c b/hw/xen/xen_pt_graphics.c
48
+ */
33
index XXXXXXX..XXXXXXX 100644
49
+static MemTxResult get_cte(GICv3ITSState *s, uint16_t icid, CTEntry *cte)
34
--- a/hw/xen/xen_pt_graphics.c
35
+++ b/hw/xen/xen_pt_graphics.c
36
@@ -XXX,XX +XXX,XX @@ int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev)
37
static void *get_vgabios(XenPCIPassthroughState *s, int *size,
38
XenHostPCIDevice *dev)
50
{
39
{
51
AddressSpace *as = &s->gicv3->dma_as;
40
- return pci_assign_dev_load_option_rom(&s->dev, OBJECT(&s->dev), size,
52
- uint64_t entry_addr = table_entry_addr(s, &s->ct, icid, res);
41
+ return pci_assign_dev_load_option_rom(&s->dev, size,
53
+ MemTxResult res = MEMTX_OK;
42
dev->domain, dev->bus,
54
+ uint64_t entry_addr = table_entry_addr(s, &s->ct, icid, &res);
43
dev->dev, dev->func);
55
+ uint64_t cteval;
56
57
if (entry_addr == -1) {
58
- return false; /* not valid */
59
+ /* No L2 table entry, i.e. no valid CTE, or a memory error */
60
+ cte->valid = false;
61
+ return res;
62
}
63
64
- *cte = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, res);
65
- return FIELD_EX64(*cte, CTE, VALID);
66
+ cteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res);
67
+ if (res != MEMTX_OK) {
68
+ return res;
69
+ }
70
+ cte->valid = FIELD_EX64(cteval, CTE, VALID);
71
+ cte->rdbase = FIELD_EX64(cteval, CTE, RDBASE);
72
+ return MEMTX_OK;
73
}
44
}
74
45
diff --git a/hw/xen/xen_pt_load_rom.c b/hw/xen/xen_pt_load_rom.c
75
static bool update_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
46
index XXXXXXX..XXXXXXX 100644
76
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
47
--- a/hw/xen/xen_pt_load_rom.c
77
uint16_t icid = 0;
48
+++ b/hw/xen/xen_pt_load_rom.c
78
uint32_t pIntid = 0;
49
@@ -XXX,XX +XXX,XX @@
79
bool ite_valid = false;
50
* load the corresponding ROM data to RAM. If an error occurs while loading an
80
- uint64_t cte = 0;
51
* option ROM, we just ignore that option ROM and continue with the next one.
81
- bool cte_valid = false;
52
*/
82
- uint64_t rdbase;
53
-void *pci_assign_dev_load_option_rom(PCIDevice *dev, struct Object *owner,
83
DTEntry dte;
54
+void *pci_assign_dev_load_option_rom(PCIDevice *dev,
84
+ CTEntry cte;
55
int *size, unsigned int domain,
85
56
unsigned int bus, unsigned int slot,
86
if (devid >= s->dt.num_entries) {
57
unsigned int function)
87
qemu_log_mask(LOG_GUEST_ERROR,
58
@@ -XXX,XX +XXX,XX @@ void *pci_assign_dev_load_option_rom(PCIDevice *dev, struct Object *owner,
88
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
59
uint8_t val;
89
return CMD_CONTINUE;
60
struct stat st;
90
}
61
void *ptr = NULL;
91
62
+ Object *owner = OBJECT(dev);
92
- cte_valid = get_cte(s, icid, &cte, &res);
63
93
- if (res != MEMTX_OK) {
64
/* If loading ROM from file, pci handles it */
94
+ if (get_cte(s, icid, &cte) != MEMTX_OK) {
65
if (dev->romfile || !dev->rom_bar) {
95
return CMD_STALL;
66
@@ -XXX,XX +XXX,XX @@ void *pci_assign_dev_load_option_rom(PCIDevice *dev, struct Object *owner,
96
}
67
fseek(fp, 0, SEEK_SET);
97
- if (!cte_valid) {
68
98
+ if (!cte.valid) {
69
snprintf(name, sizeof(name), "%s.rom", object_get_typename(owner));
99
qemu_log_mask(LOG_GUEST_ERROR,
70
- memory_region_init_ram_nomigrate(&dev->rom, owner, name, st.st_size, &error_abort);
100
- "%s: invalid command attributes: "
71
- vmstate_register_ram(&dev->rom, &dev->qdev);
101
- "invalid cte: %"PRIx64"\n",
72
+ memory_region_init_ram(&dev->rom, owner, name, st.st_size, &error_abort);
102
- __func__, cte);
73
ptr = memory_region_get_ram_ptr(&dev->rom);
103
+ "%s: invalid command attributes: invalid CTE\n",
74
memset(ptr, 0xff, st.st_size);
104
+ __func__);
105
return CMD_CONTINUE;
106
}
107
108
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
109
* Current implementation only supports rdbase == procnum
110
* Hence rdbase physical address is ignored
111
*/
112
- rdbase = FIELD_EX64(cte, CTE, RDBASE);
113
-
114
- if (rdbase >= s->gicv3->num_cpu) {
115
+ if (cte.rdbase >= s->gicv3->num_cpu) {
116
return CMD_CONTINUE;
117
}
118
119
if ((cmd == CLEAR) || (cmd == DISCARD)) {
120
- gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 0);
121
+ gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], pIntid, 0);
122
} else {
123
- gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 1);
124
+ gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], pIntid, 1);
125
}
126
127
if (cmd == DISCARD) {
128
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
129
MemTxResult res = MEMTX_OK;
130
uint32_t devid, eventid, intid;
131
uint16_t old_icid, new_icid;
132
- uint64_t old_cte, new_cte;
133
- uint64_t old_rdbase, new_rdbase;
134
- bool ite_valid, cte_valid;
135
+ bool ite_valid;
136
uint64_t num_eventids;
137
IteEntry ite = {};
138
DTEntry dte;
139
+ CTEntry old_cte, new_cte;
140
141
devid = FIELD_EX64(cmdpkt[0], MOVI_0, DEVICEID);
142
eventid = FIELD_EX64(cmdpkt[1], MOVI_1, EVENTID);
143
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
144
return CMD_CONTINUE;
145
}
146
147
- cte_valid = get_cte(s, old_icid, &old_cte, &res);
148
- if (res != MEMTX_OK) {
149
+ if (get_cte(s, old_icid, &old_cte) != MEMTX_OK) {
150
return CMD_STALL;
151
}
152
- if (!cte_valid) {
153
+ if (!old_cte.valid) {
154
qemu_log_mask(LOG_GUEST_ERROR,
155
"%s: invalid command attributes: "
156
- "invalid cte: %"PRIx64"\n",
157
- __func__, old_cte);
158
+ "invalid CTE for old ICID 0x%x\n",
159
+ __func__, old_icid);
160
return CMD_CONTINUE;
161
}
162
163
- cte_valid = get_cte(s, new_icid, &new_cte, &res);
164
- if (res != MEMTX_OK) {
165
+ if (get_cte(s, new_icid, &new_cte) != MEMTX_OK) {
166
return CMD_STALL;
167
}
168
- if (!cte_valid) {
169
+ if (!new_cte.valid) {
170
qemu_log_mask(LOG_GUEST_ERROR,
171
"%s: invalid command attributes: "
172
- "invalid cte: %"PRIx64"\n",
173
- __func__, new_cte);
174
+ "invalid CTE for new ICID 0x%x\n",
175
+ __func__, new_icid);
176
return CMD_CONTINUE;
177
}
178
179
- old_rdbase = FIELD_EX64(old_cte, CTE, RDBASE);
180
- if (old_rdbase >= s->gicv3->num_cpu) {
181
+ if (old_cte.rdbase >= s->gicv3->num_cpu) {
182
qemu_log_mask(LOG_GUEST_ERROR,
183
- "%s: CTE has invalid rdbase 0x%"PRIx64"\n",
184
- __func__, old_rdbase);
185
+ "%s: CTE has invalid rdbase 0x%x\n",
186
+ __func__, old_cte.rdbase);
187
return CMD_CONTINUE;
188
}
189
190
- new_rdbase = FIELD_EX64(new_cte, CTE, RDBASE);
191
- if (new_rdbase >= s->gicv3->num_cpu) {
192
+ if (new_cte.rdbase >= s->gicv3->num_cpu) {
193
qemu_log_mask(LOG_GUEST_ERROR,
194
- "%s: CTE has invalid rdbase 0x%"PRIx64"\n",
195
- __func__, new_rdbase);
196
+ "%s: CTE has invalid rdbase 0x%x\n",
197
+ __func__, new_cte.rdbase);
198
return CMD_CONTINUE;
199
}
200
201
- if (old_rdbase != new_rdbase) {
202
+ if (old_cte.rdbase != new_cte.rdbase) {
203
/* Move the LPI from the old redistributor to the new one */
204
- gicv3_redist_mov_lpi(&s->gicv3->cpu[old_rdbase],
205
- &s->gicv3->cpu[new_rdbase],
206
+ gicv3_redist_mov_lpi(&s->gicv3->cpu[old_cte.rdbase],
207
+ &s->gicv3->cpu[new_cte.rdbase],
208
intid);
209
}
210
75
211
--
76
--
212
2.25.1
77
2.17.1
213
78
214
79
diff view generated by jsdifflib
Deleted patch
1
In get_ite() and update_ite() we work with a 12-byte in-guest-memory
2
table entry, which we intend to handle as an 8-byte value followed by
3
a 4-byte value. Unfortunately the calculation of the address of the
4
4-byte value is wrong, because we write it as:
5
1
6
table_base_address + (index * entrysize) + 4
7
(obfuscated by the way the expression has been written)
8
9
when it should be + 8. This bug meant that we overwrote the top
10
bytes of the 8-byte value with the 4-byte value. There are no
11
guest-visible effects because the top half of the 8-byte value
12
contains only the doorbell interrupt field, which is used only in
13
GICv4, and the two bugs in the "write ITE" and "read ITE" codepaths
14
cancel each other out.
15
16
We can't simply change the calculation, because this would break
17
migration of a (TCG) guest from the old version of QEMU which had
18
in-guest-memory interrupt tables written using the buggy version of
19
update_ite(). We must also at the same time change the layout of the
20
fields within the ITE_L and ITE_H values so that the in-memory
21
locations of the fields we care about (VALID, INTTYPE, INTID and
22
ICID) stay the same.
23
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Message-id: 20220201193207.2771604-7-peter.maydell@linaro.org
27
---
28
hw/intc/gicv3_internal.h | 19 ++++++++++---------
29
hw/intc/arm_gicv3_its.c | 28 +++++++++++-----------------
30
2 files changed, 21 insertions(+), 26 deletions(-)
31
32
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/intc/gicv3_internal.h
35
+++ b/hw/intc/gicv3_internal.h
36
@@ -XXX,XX +XXX,XX @@ FIELD(MOVI_2, ICID, 0, 16)
37
* 12 bytes Interrupt translation Table Entry size
38
* as per Table 5.3 in GICv3 spec
39
* ITE Lower 8 Bytes
40
- * Bits: | 49 ... 26 | 25 ... 2 | 1 | 0 |
41
- * Values: | Doorbell | IntNum | IntType | Valid |
42
+ * Bits: | 63 ... 48 | 47 ... 32 | 31 ... 26 | 25 ... 2 | 1 | 0 |
43
+ * Values: | vPEID | ICID | unused | IntNum | IntType | Valid |
44
* ITE Higher 4 Bytes
45
- * Bits: | 31 ... 16 | 15 ...0 |
46
- * Values: | vPEID | ICID |
47
- * (When Doorbell is unused, as it always is in GICv3, it is 1023)
48
+ * Bits: | 31 ... 25 | 24 ... 0 |
49
+ * Values: | unused | Doorbell |
50
+ * (When Doorbell is unused, as it always is for INTYPE_PHYSICAL,
51
+ * the value of that field in memory cannot be relied upon -- older
52
+ * versions of QEMU did not correctly write to that memory.)
53
*/
54
#define ITS_ITT_ENTRY_SIZE 0xC
55
56
FIELD(ITE_L, VALID, 0, 1)
57
FIELD(ITE_L, INTTYPE, 1, 1)
58
FIELD(ITE_L, INTID, 2, 24)
59
-FIELD(ITE_L, DOORBELL, 26, 24)
60
-
61
-FIELD(ITE_H, ICID, 0, 16)
62
-FIELD(ITE_H, VPEID, 16, 16)
63
+FIELD(ITE_L, ICID, 32, 16)
64
+FIELD(ITE_L, VPEID, 48, 16)
65
+FIELD(ITE_H, DOORBELL, 0, 24)
66
67
/* Possible values for ITE_L INTTYPE */
68
#define ITE_INTTYPE_VIRTUAL 0
69
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/hw/intc/arm_gicv3_its.c
72
+++ b/hw/intc/arm_gicv3_its.c
73
@@ -XXX,XX +XXX,XX @@ static bool update_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
74
{
75
AddressSpace *as = &s->gicv3->dma_as;
76
MemTxResult res = MEMTX_OK;
77
+ hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
78
79
- address_space_stq_le(as, dte->ittaddr + (eventid * (sizeof(uint64_t) +
80
- sizeof(uint32_t))), ite.itel, MEMTXATTRS_UNSPECIFIED,
81
- &res);
82
+ address_space_stq_le(as, iteaddr, ite.itel, MEMTXATTRS_UNSPECIFIED, &res);
83
84
if (res == MEMTX_OK) {
85
- address_space_stl_le(as, dte->ittaddr + (eventid * (sizeof(uint64_t) +
86
- sizeof(uint32_t))) + sizeof(uint32_t), ite.iteh,
87
+ address_space_stl_le(as, iteaddr + 8, ite.iteh,
88
MEMTXATTRS_UNSPECIFIED, &res);
89
}
90
if (res != MEMTX_OK) {
91
@@ -XXX,XX +XXX,XX @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
92
AddressSpace *as = &s->gicv3->dma_as;
93
bool status = false;
94
IteEntry ite = {};
95
+ hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
96
97
- ite.itel = address_space_ldq_le(as, dte->ittaddr +
98
- (eventid * (sizeof(uint64_t) +
99
- sizeof(uint32_t))), MEMTXATTRS_UNSPECIFIED,
100
- res);
101
+ ite.itel = address_space_ldq_le(as, iteaddr, MEMTXATTRS_UNSPECIFIED, res);
102
103
if (*res == MEMTX_OK) {
104
- ite.iteh = address_space_ldl_le(as, dte->ittaddr +
105
- (eventid * (sizeof(uint64_t) +
106
- sizeof(uint32_t))) + sizeof(uint32_t),
107
+ ite.iteh = address_space_ldl_le(as, iteaddr + 8,
108
MEMTXATTRS_UNSPECIFIED, res);
109
110
if (*res == MEMTX_OK) {
111
@@ -XXX,XX +XXX,XX @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
112
int inttype = FIELD_EX64(ite.itel, ITE_L, INTTYPE);
113
if (inttype == ITE_INTTYPE_PHYSICAL) {
114
*pIntid = FIELD_EX64(ite.itel, ITE_L, INTID);
115
- *icid = FIELD_EX32(ite.iteh, ITE_H, ICID);
116
+ *icid = FIELD_EX64(ite.itel, ITE_L, ICID);
117
status = true;
118
}
119
}
120
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
121
ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, true);
122
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
123
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid);
124
- ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
125
- ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid);
126
+ ite.itel = FIELD_DP64(ite.itel, ITE_L, ICID, icid);
127
+ ite.iteh = FIELD_DP32(ite.iteh, ITE_H, DOORBELL, INTID_SPURIOUS);
128
129
return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
130
}
131
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
132
ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, 1);
133
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
134
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, intid);
135
- ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
136
- ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, new_icid);
137
+ ite.itel = FIELD_DP64(ite.itel, ITE_L, ICID, new_icid);
138
+ ite.iteh = FIELD_DP32(ite.iteh, ITE_H, DOORBELL, INTID_SPURIOUS);
139
return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
140
}
141
142
--
143
2.25.1
144
145
diff view generated by jsdifflib
Deleted patch
1
The get_ite() code has some awkward nested if statements; clean
2
them up by returning early if the memory accesses fail.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20220201193207.2771604-8-peter.maydell@linaro.org
7
---
8
hw/intc/arm_gicv3_its.c | 26 ++++++++++++++------------
9
1 file changed, 14 insertions(+), 12 deletions(-)
10
11
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/intc/arm_gicv3_its.c
14
+++ b/hw/intc/arm_gicv3_its.c
15
@@ -XXX,XX +XXX,XX @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
16
hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
17
18
ite.itel = address_space_ldq_le(as, iteaddr, MEMTXATTRS_UNSPECIFIED, res);
19
+ if (*res != MEMTX_OK) {
20
+ return false;
21
+ }
22
23
- if (*res == MEMTX_OK) {
24
- ite.iteh = address_space_ldl_le(as, iteaddr + 8,
25
- MEMTXATTRS_UNSPECIFIED, res);
26
+ ite.iteh = address_space_ldl_le(as, iteaddr + 8,
27
+ MEMTXATTRS_UNSPECIFIED, res);
28
+ if (*res != MEMTX_OK) {
29
+ return false;
30
+ }
31
32
- if (*res == MEMTX_OK) {
33
- if (FIELD_EX64(ite.itel, ITE_L, VALID)) {
34
- int inttype = FIELD_EX64(ite.itel, ITE_L, INTTYPE);
35
- if (inttype == ITE_INTTYPE_PHYSICAL) {
36
- *pIntid = FIELD_EX64(ite.itel, ITE_L, INTID);
37
- *icid = FIELD_EX64(ite.itel, ITE_L, ICID);
38
- status = true;
39
- }
40
- }
41
+ if (FIELD_EX64(ite.itel, ITE_L, VALID)) {
42
+ int inttype = FIELD_EX64(ite.itel, ITE_L, INTTYPE);
43
+ if (inttype == ITE_INTTYPE_PHYSICAL) {
44
+ *pIntid = FIELD_EX64(ite.itel, ITE_L, INTID);
45
+ *icid = FIELD_EX64(ite.itel, ITE_L, ICID);
46
+ status = true;
47
}
48
}
49
return status;
50
--
51
2.25.1
52
53
diff view generated by jsdifflib
Deleted patch
1
In get_ite() we currently return the caller some of the fields of an
2
Interrupt Table Entry via a set of pointer arguments, and validate
3
some of them internally (interrupt type and valid bit) to return a
4
simple true/false 'valid' indication. Define a new ITEntry struct
5
which has all the fields that the in-memory ITE has, and bring the
6
get_ite() function in to line with get_dte() and get_cte().
7
1
8
This paves the way for handling virtual interrupts, which will want
9
a different subset of the fields in the ITE. Handling them under
10
the old "lots of pointer arguments" scheme would have meant a
11
confusingly large set of arguments for this function.
12
13
The new struct ITEntry is obviously confusably similar to the
14
existing IteEntry struct, whose fields are the raw 12 bytes
15
of the in-memory ITE. In the next commit we will make update_ite()
16
use ITEntry instead of IteEntry, which will allow us to delete
17
the IteEntry struct and remove the confusion.
18
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20220201193207.2771604-9-peter.maydell@linaro.org
22
---
23
hw/intc/arm_gicv3_its.c | 102 ++++++++++++++++++++++------------------
24
1 file changed, 55 insertions(+), 47 deletions(-)
25
26
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/intc/arm_gicv3_its.c
29
+++ b/hw/intc/arm_gicv3_its.c
30
@@ -XXX,XX +XXX,XX @@ typedef struct CTEntry {
31
uint32_t rdbase;
32
} CTEntry;
33
34
+typedef struct ITEntry {
35
+ bool valid;
36
+ int inttype;
37
+ uint32_t intid;
38
+ uint32_t doorbell;
39
+ uint32_t icid;
40
+ uint32_t vpeid;
41
+} ITEntry;
42
+
43
+
44
/*
45
* The ITS spec permits a range of CONSTRAINED UNPREDICTABLE options
46
* if a command parameter is not correct. These include both "stall
47
@@ -XXX,XX +XXX,XX @@ static bool update_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
48
}
49
}
50
51
-static bool get_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
52
- uint16_t *icid, uint32_t *pIntid, MemTxResult *res)
53
+/*
54
+ * Read the Interrupt Table entry at index @eventid from the table specified
55
+ * by the DTE @dte. On success, we return MEMTX_OK and populate the ITEntry
56
+ * struct @ite accordingly. If there is an error reading memory then we return
57
+ * the error code.
58
+ */
59
+static MemTxResult get_ite(GICv3ITSState *s, uint32_t eventid,
60
+ const DTEntry *dte, ITEntry *ite)
61
{
62
AddressSpace *as = &s->gicv3->dma_as;
63
- bool status = false;
64
- IteEntry ite = {};
65
+ MemTxResult res = MEMTX_OK;
66
+ uint64_t itel;
67
+ uint32_t iteh;
68
hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
69
70
- ite.itel = address_space_ldq_le(as, iteaddr, MEMTXATTRS_UNSPECIFIED, res);
71
- if (*res != MEMTX_OK) {
72
- return false;
73
+ itel = address_space_ldq_le(as, iteaddr, MEMTXATTRS_UNSPECIFIED, &res);
74
+ if (res != MEMTX_OK) {
75
+ return res;
76
}
77
78
- ite.iteh = address_space_ldl_le(as, iteaddr + 8,
79
- MEMTXATTRS_UNSPECIFIED, res);
80
- if (*res != MEMTX_OK) {
81
- return false;
82
+ iteh = address_space_ldl_le(as, iteaddr + 8, MEMTXATTRS_UNSPECIFIED, &res);
83
+ if (res != MEMTX_OK) {
84
+ return res;
85
}
86
87
- if (FIELD_EX64(ite.itel, ITE_L, VALID)) {
88
- int inttype = FIELD_EX64(ite.itel, ITE_L, INTTYPE);
89
- if (inttype == ITE_INTTYPE_PHYSICAL) {
90
- *pIntid = FIELD_EX64(ite.itel, ITE_L, INTID);
91
- *icid = FIELD_EX64(ite.itel, ITE_L, ICID);
92
- status = true;
93
- }
94
- }
95
- return status;
96
+ ite->valid = FIELD_EX64(itel, ITE_L, VALID);
97
+ ite->inttype = FIELD_EX64(itel, ITE_L, INTTYPE);
98
+ ite->intid = FIELD_EX64(itel, ITE_L, INTID);
99
+ ite->icid = FIELD_EX64(itel, ITE_L, ICID);
100
+ ite->vpeid = FIELD_EX64(itel, ITE_L, VPEID);
101
+ ite->doorbell = FIELD_EX64(iteh, ITE_H, DOORBELL);
102
+ return MEMTX_OK;
103
}
104
105
/*
106
@@ -XXX,XX +XXX,XX @@ static MemTxResult get_dte(GICv3ITSState *s, uint32_t devid, DTEntry *dte)
107
static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
108
uint32_t eventid, ItsCmdType cmd)
109
{
110
- MemTxResult res = MEMTX_OK;
111
uint64_t num_eventids;
112
- uint16_t icid = 0;
113
- uint32_t pIntid = 0;
114
- bool ite_valid = false;
115
DTEntry dte;
116
CTEntry cte;
117
+ ITEntry ite;
118
119
if (devid >= s->dt.num_entries) {
120
qemu_log_mask(LOG_GUEST_ERROR,
121
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
122
return CMD_CONTINUE;
123
}
124
125
- ite_valid = get_ite(s, eventid, &dte, &icid, &pIntid, &res);
126
- if (res != MEMTX_OK) {
127
+ if (get_ite(s, eventid, &dte, &ite) != MEMTX_OK) {
128
return CMD_STALL;
129
}
130
131
- if (!ite_valid) {
132
+ if (!ite.valid || ite.inttype != ITE_INTTYPE_PHYSICAL) {
133
qemu_log_mask(LOG_GUEST_ERROR,
134
"%s: invalid command attributes: invalid ITE\n",
135
__func__);
136
return CMD_CONTINUE;
137
}
138
139
- if (icid >= s->ct.num_entries) {
140
+ if (ite.icid >= s->ct.num_entries) {
141
qemu_log_mask(LOG_GUEST_ERROR,
142
"%s: invalid ICID 0x%x in ITE (table corrupted?)\n",
143
- __func__, icid);
144
+ __func__, ite.icid);
145
return CMD_CONTINUE;
146
}
147
148
- if (get_cte(s, icid, &cte) != MEMTX_OK) {
149
+ if (get_cte(s, ite.icid, &cte) != MEMTX_OK) {
150
return CMD_STALL;
151
}
152
if (!cte.valid) {
153
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
154
}
155
156
if ((cmd == CLEAR) || (cmd == DISCARD)) {
157
- gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], pIntid, 0);
158
+ gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], ite.intid, 0);
159
} else {
160
- gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], pIntid, 1);
161
+ gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], ite.intid, 1);
162
}
163
164
if (cmd == DISCARD) {
165
- IteEntry ite = {};
166
+ IteEntry itee = {};
167
/* remove mapping from interrupt translation table */
168
- return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
169
+ return update_ite(s, eventid, &dte, itee) ? CMD_CONTINUE : CMD_STALL;
170
}
171
return CMD_CONTINUE;
172
}
173
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movall(GICv3ITSState *s, const uint64_t *cmdpkt)
174
175
static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
176
{
177
- MemTxResult res = MEMTX_OK;
178
- uint32_t devid, eventid, intid;
179
- uint16_t old_icid, new_icid;
180
- bool ite_valid;
181
+ uint32_t devid, eventid;
182
+ uint16_t new_icid;
183
uint64_t num_eventids;
184
IteEntry ite = {};
185
DTEntry dte;
186
CTEntry old_cte, new_cte;
187
+ ITEntry old_ite;
188
189
devid = FIELD_EX64(cmdpkt[0], MOVI_0, DEVICEID);
190
eventid = FIELD_EX64(cmdpkt[1], MOVI_1, EVENTID);
191
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
192
return CMD_CONTINUE;
193
}
194
195
- ite_valid = get_ite(s, eventid, &dte, &old_icid, &intid, &res);
196
- if (res != MEMTX_OK) {
197
+ if (get_ite(s, eventid, &dte, &old_ite) != MEMTX_OK) {
198
return CMD_STALL;
199
}
200
201
- if (!ite_valid) {
202
+ if (!old_ite.valid || old_ite.inttype != ITE_INTTYPE_PHYSICAL) {
203
qemu_log_mask(LOG_GUEST_ERROR,
204
"%s: invalid command attributes: invalid ITE\n",
205
__func__);
206
return CMD_CONTINUE;
207
}
208
209
- if (old_icid >= s->ct.num_entries) {
210
+ if (old_ite.icid >= s->ct.num_entries) {
211
qemu_log_mask(LOG_GUEST_ERROR,
212
"%s: invalid ICID 0x%x in ITE (table corrupted?)\n",
213
- __func__, old_icid);
214
+ __func__, old_ite.icid);
215
return CMD_CONTINUE;
216
}
217
218
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
219
return CMD_CONTINUE;
220
}
221
222
- if (get_cte(s, old_icid, &old_cte) != MEMTX_OK) {
223
+ if (get_cte(s, old_ite.icid, &old_cte) != MEMTX_OK) {
224
return CMD_STALL;
225
}
226
if (!old_cte.valid) {
227
qemu_log_mask(LOG_GUEST_ERROR,
228
"%s: invalid command attributes: "
229
"invalid CTE for old ICID 0x%x\n",
230
- __func__, old_icid);
231
+ __func__, old_ite.icid);
232
return CMD_CONTINUE;
233
}
234
235
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
236
/* Move the LPI from the old redistributor to the new one */
237
gicv3_redist_mov_lpi(&s->gicv3->cpu[old_cte.rdbase],
238
&s->gicv3->cpu[new_cte.rdbase],
239
- intid);
240
+ old_ite.intid);
241
}
242
243
/* Update the ICID field in the interrupt translation table entry */
244
ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, 1);
245
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
246
- ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, intid);
247
+ ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, old_ite.intid);
248
ite.itel = FIELD_DP64(ite.itel, ITE_L, ICID, new_icid);
249
ite.iteh = FIELD_DP32(ite.iteh, ITE_H, DOORBELL, INTID_SPURIOUS);
250
return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
251
--
252
2.25.1
253
254
diff view generated by jsdifflib
Deleted patch
1
Currently we track in the TableDesc and CmdQDesc structs the state of
2
the GITS_BASER<n> and GITS_CBASER Valid bits. However we aren't very
3
consistent abut checking the valid field: we test it in update_cte()
4
and update_dte(), but not anywhere else we look things up in tables.
5
1
6
The GIC specification says that it is UNPREDICTABLE if a guest fails
7
to set any of these Valid bits before enabling the ITS via
8
GITS_CTLR.Enabled. So we can choose to handle Valid == 0 as
9
equivalent to a zero-length table. This is in fact how we're already
10
catching this case in most of the table-access paths: when Valid is 0
11
we leave the num_entries fields in TableDesc or CmdQDesc set to zero,
12
and then the out-of-bounds check "index >= num_entries" that we have
13
to do anyway before doing any of these table lookups will always be
14
true, catching the no-valid-table case without any extra code.
15
16
So we can remove the checks on the valid field from update_cte()
17
and update_dte(): since these happen after the bounds check there
18
was never any case when the test could fail. That means the valid
19
fields would be entirely unused, so just remove them.
20
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 20220201193207.2771604-11-peter.maydell@linaro.org
24
---
25
include/hw/intc/arm_gicv3_its_common.h | 2 --
26
hw/intc/arm_gicv3_its.c | 31 ++++++++++++--------------
27
2 files changed, 14 insertions(+), 19 deletions(-)
28
29
diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/include/hw/intc/arm_gicv3_its_common.h
32
+++ b/include/hw/intc/arm_gicv3_its_common.h
33
@@ -XXX,XX +XXX,XX @@
34
#define GITS_TRANSLATER 0x0040
35
36
typedef struct {
37
- bool valid;
38
bool indirect;
39
uint16_t entry_sz;
40
uint32_t page_sz;
41
@@ -XXX,XX +XXX,XX @@ typedef struct {
42
} TableDesc;
43
44
typedef struct {
45
- bool valid;
46
uint32_t num_entries;
47
uint64_t base_addr;
48
} CmdQDesc;
49
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/intc/arm_gicv3_its.c
52
+++ b/hw/intc/arm_gicv3_its.c
53
@@ -XXX,XX +XXX,XX @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, const CTEntry *cte)
54
uint64_t cteval = 0;
55
MemTxResult res = MEMTX_OK;
56
57
- if (!s->ct.valid) {
58
- return true;
59
- }
60
-
61
if (cte->valid) {
62
/* add mapping entry to collection table */
63
cteval = FIELD_DP64(cteval, CTE, VALID, 1);
64
@@ -XXX,XX +XXX,XX @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, const DTEntry *dte)
65
uint64_t dteval = 0;
66
MemTxResult res = MEMTX_OK;
67
68
- if (s->dt.valid) {
69
- if (dte->valid) {
70
- /* add mapping entry to device table */
71
- dteval = FIELD_DP64(dteval, DTE, VALID, 1);
72
- dteval = FIELD_DP64(dteval, DTE, SIZE, dte->size);
73
- dteval = FIELD_DP64(dteval, DTE, ITTADDR, dte->ittaddr);
74
- }
75
- } else {
76
- return true;
77
+ if (dte->valid) {
78
+ /* add mapping entry to device table */
79
+ dteval = FIELD_DP64(dteval, DTE, VALID, 1);
80
+ dteval = FIELD_DP64(dteval, DTE, SIZE, dte->size);
81
+ dteval = FIELD_DP64(dteval, DTE, ITTADDR, dte->ittaddr);
82
}
83
84
entry_addr = table_entry_addr(s, &s->dt, devid, &res);
85
@@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s)
86
}
87
88
memset(td, 0, sizeof(*td));
89
- td->valid = FIELD_EX64(value, GITS_BASER, VALID);
90
/*
91
* If GITS_BASER<n>.Valid is 0 for any <n> then we will not process
92
* interrupts. (GITS_TYPER.HCC is 0 for this implementation, so we
93
@@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s)
94
* for the register corresponding to the Collection table but we
95
* still have to process interrupts using non-memory-backed
96
* Collection table entries.)
97
+ * The specification makes it UNPREDICTABLE to enable the ITS without
98
+ * marking each BASER<n> as valid. We choose to handle these as if
99
+ * the table was zero-sized, so commands using the table will fail
100
+ * and interrupts requested via GITS_TRANSLATER writes will be ignored.
101
+ * This happens automatically by leaving the num_entries field at
102
+ * zero, which will be caught by the bounds checks we have before
103
+ * every table lookup anyway.
104
*/
105
- if (!td->valid) {
106
+ if (!FIELD_EX64(value, GITS_BASER, VALID)) {
107
continue;
108
}
109
td->page_sz = page_sz;
110
@@ -XXX,XX +XXX,XX @@ static void extract_cmdq_params(GICv3ITSState *s)
111
num_pages = FIELD_EX64(value, GITS_CBASER, SIZE) + 1;
112
113
memset(&s->cq, 0 , sizeof(s->cq));
114
- s->cq.valid = FIELD_EX64(value, GITS_CBASER, VALID);
115
116
- if (s->cq.valid) {
117
+ if (FIELD_EX64(value, GITS_CBASER, VALID)) {
118
s->cq.num_entries = (num_pages * GITS_PAGE_SIZE_4K) /
119
GITS_CMDQ_ENTRY_SIZE;
120
s->cq.base_addr = FIELD_EX64(value, GITS_CBASER, PHYADDR);
121
--
122
2.25.1
123
124
diff view generated by jsdifflib