1
Second pull request of the week; mostly RTH's support for some
1
Last pullreq before 6.0 softfreeze: a few minor feature patches,
2
new-in-v8.1/v8.3 instructions, and my v8M board model.
2
some bugfixes, some cleanups.
3
3
4
thanks
5
-- PMM
4
-- PMM
6
5
7
The following changes since commit 427cbc7e4136a061628cb4315cc8182ea36d772f:
6
The following changes since commit 6f34661b6c97a37a5efc27d31c037ddeda4547e2:
8
7
9
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2018-03-01 18:46:41 +0000)
8
Merge remote-tracking branch 'remotes/vivier2/tags/trivial-branch-for-6.0-pull-request' into staging (2021-03-11 18:55:27 +0000)
10
9
11
are available in the Git repository at:
10
are available in the Git repository at:
12
11
13
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180302
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210312-1
14
13
15
for you to fetch changes up to e66a67bf28e1b4fce2e3d72a2610dbd48d9d3078:
14
for you to fetch changes up to 41f09f2e9f09e4dd386d84174a6dcb5136af17ca:
16
15
17
target/arm: Enable ARM_FEATURE_V8_FCMA (2018-03-02 11:03:45 +0000)
16
hw/display/pxa2xx: Inline template header (2021-03-12 13:26:08 +0000)
18
17
19
----------------------------------------------------------------
18
----------------------------------------------------------------
20
target-arm queue:
19
target-arm queue:
21
* implement FCMA and RDM v8.1 and v8.3 instructions
20
* versal: Support XRAMs and XRAM controller
22
* enable Cortex-M33 v8M core, and provide new mps2-an505 board model
21
* smmu: Various minor bug fixes
23
that uses it
22
* SVE emulation: fix bugs handling odd vector lengths
24
* decodetree: Propagate return value from translate subroutines
23
* allwinner-sun8i-emac: traverse transmit queue using TX_CUR_DESC register value
25
* xlnx-zynqmp: Implement the RTC device
24
* tests/acceptance: fix orangepi-pc acceptance tests
25
* hw/timer/sse-timer: Propagate eventual error in sse_timer_realize()
26
* hw/arm/virt: KVM: The IPA lower bound is 32
27
* npcm7xx: support MFT module
28
* pl110, pxa2xx_lcd: tidy up template headers
26
29
27
----------------------------------------------------------------
30
----------------------------------------------------------------
28
Alistair Francis (3):
31
Andrew Jones (2):
29
xlnx-zynqmp-rtc: Initial commit
32
accel: kvm: Fix kvm_type invocation
30
xlnx-zynqmp-rtc: Add basic time support
33
hw/arm/virt: KVM: The IPA lower bound is 32
31
xlnx-zynqmp: Connect the RTC device
32
34
33
Peter Maydell (19):
35
Edgar E. Iglesias (2):
34
loader: Add new load_ramdisk_as()
36
hw/misc: versal: Add a model of the XRAM controller
35
hw/arm/boot: Honour CPU's address space for image loads
37
hw/arm: versal: Add support for the XRAMs
36
hw/arm/armv7m: Honour CPU's address space for image loads
37
target/arm: Define an IDAU interface
38
armv7m: Forward idau property to CPU object
39
target/arm: Define init-svtor property for the reset secure VTOR value
40
armv7m: Forward init-svtor property to CPU object
41
target/arm: Add Cortex-M33
42
hw/misc/unimp: Move struct to header file
43
include/hw/or-irq.h: Add missing include guard
44
qdev: Add new qdev_init_gpio_in_named_with_opaque()
45
hw/core/split-irq: Device that splits IRQ lines
46
hw/misc/mps2-fpgaio: FPGA control block for MPS2 AN505
47
hw/misc/tz-ppc: Model TrustZone peripheral protection controller
48
hw/misc/iotkit-secctl: Arm IoT Kit security controller initial skeleton
49
hw/misc/iotkit-secctl: Add handling for PPCs
50
hw/misc/iotkit-secctl: Add remaining simple registers
51
hw/arm/iotkit: Model Arm IOT Kit
52
mps2-an505: New board model: MPS2 with AN505 Cortex-M33 FPGA image
53
38
54
Richard Henderson (17):
39
Eric Auger (7):
55
decodetree: Propagate return value from translate subroutines
40
intel_iommu: Fix mask may be uninitialized in vtd_context_device_invalidate
56
target/arm: Add ARM_FEATURE_V8_RDM
41
dma: Introduce dma_aligned_pow2_mask()
57
target/arm: Refactor disas_simd_indexed decode
42
virtio-iommu: Handle non power of 2 range invalidations
58
target/arm: Refactor disas_simd_indexed size checks
43
hw/arm/smmu-common: Fix smmu_iotlb_inv_iova when asid is not set
59
target/arm: Decode aa64 armv8.1 scalar three same extra
44
hw/arm/smmuv3: Enforce invalidation on a power of two range
60
target/arm: Decode aa64 armv8.1 three same extra
45
hw/arm/smmuv3: Fix SMMU_CMD_CFGI_STE_RANGE handling
61
target/arm: Decode aa64 armv8.1 scalar/vector x indexed element
46
hw/arm/smmuv3: Uniformize sid traces
62
target/arm: Decode aa32 armv8.1 three same
63
target/arm: Decode aa32 armv8.1 two reg and a scalar
64
target/arm: Enable ARM_FEATURE_V8_RDM
65
target/arm: Add ARM_FEATURE_V8_FCMA
66
target/arm: Decode aa64 armv8.3 fcadd
67
target/arm: Decode aa64 armv8.3 fcmla
68
target/arm: Decode aa32 armv8.3 3-same
69
target/arm: Decode aa32 armv8.3 2-reg-index
70
target/arm: Decode t32 simd 3reg and 2reg_scalar extension
71
target/arm: Enable ARM_FEATURE_V8_FCMA
72
47
73
hw/arm/Makefile.objs | 2 +
48
Hao Wu (5):
74
hw/core/Makefile.objs | 1 +
49
hw/misc: Add GPIOs for duty in NPCM7xx PWM
75
hw/misc/Makefile.objs | 4 +
50
hw/misc: Add NPCM7XX MFT Module
76
hw/timer/Makefile.objs | 1 +
51
hw/arm: Add MFT device to NPCM7xx Soc
77
target/arm/Makefile.objs | 2 +-
52
hw/arm: Connect PWM fans in NPCM7XX boards
78
include/hw/arm/armv7m.h | 5 +
53
tests/qtest: Test PWM fan RPM using MFT in PWM test
79
include/hw/arm/iotkit.h | 109 ++++++
80
include/hw/arm/xlnx-zynqmp.h | 2 +
81
include/hw/core/split-irq.h | 57 +++
82
include/hw/irq.h | 4 +-
83
include/hw/loader.h | 12 +-
84
include/hw/misc/iotkit-secctl.h | 103 ++++++
85
include/hw/misc/mps2-fpgaio.h | 43 +++
86
include/hw/misc/tz-ppc.h | 101 ++++++
87
include/hw/misc/unimp.h | 10 +
88
include/hw/or-irq.h | 5 +
89
include/hw/qdev-core.h | 30 +-
90
include/hw/timer/xlnx-zynqmp-rtc.h | 86 +++++
91
target/arm/cpu.h | 8 +
92
target/arm/helper.h | 31 ++
93
target/arm/idau.h | 61 ++++
94
hw/arm/armv7m.c | 35 +-
95
hw/arm/boot.c | 119 ++++---
96
hw/arm/iotkit.c | 598 +++++++++++++++++++++++++++++++
97
hw/arm/mps2-tz.c | 503 ++++++++++++++++++++++++++
98
hw/arm/xlnx-zynqmp.c | 14 +
99
hw/core/loader.c | 8 +-
100
hw/core/qdev.c | 8 +-
101
hw/core/split-irq.c | 89 +++++
102
hw/misc/iotkit-secctl.c | 704 +++++++++++++++++++++++++++++++++++++
103
hw/misc/mps2-fpgaio.c | 176 ++++++++++
104
hw/misc/tz-ppc.c | 302 ++++++++++++++++
105
hw/misc/unimp.c | 10 -
106
hw/timer/xlnx-zynqmp-rtc.c | 272 ++++++++++++++
107
linux-user/elfload.c | 2 +
108
target/arm/cpu.c | 66 +++-
109
target/arm/cpu64.c | 2 +
110
target/arm/helper.c | 28 +-
111
target/arm/translate-a64.c | 514 +++++++++++++++++++++------
112
target/arm/translate.c | 275 +++++++++++++--
113
target/arm/vec_helper.c | 429 ++++++++++++++++++++++
114
default-configs/arm-softmmu.mak | 5 +
115
hw/misc/trace-events | 24 ++
116
hw/timer/trace-events | 3 +
117
scripts/decodetree.py | 5 +-
118
45 files changed, 4668 insertions(+), 200 deletions(-)
119
create mode 100644 include/hw/arm/iotkit.h
120
create mode 100644 include/hw/core/split-irq.h
121
create mode 100644 include/hw/misc/iotkit-secctl.h
122
create mode 100644 include/hw/misc/mps2-fpgaio.h
123
create mode 100644 include/hw/misc/tz-ppc.h
124
create mode 100644 include/hw/timer/xlnx-zynqmp-rtc.h
125
create mode 100644 target/arm/idau.h
126
create mode 100644 hw/arm/iotkit.c
127
create mode 100644 hw/arm/mps2-tz.c
128
create mode 100644 hw/core/split-irq.c
129
create mode 100644 hw/misc/iotkit-secctl.c
130
create mode 100644 hw/misc/mps2-fpgaio.c
131
create mode 100644 hw/misc/tz-ppc.c
132
create mode 100644 hw/timer/xlnx-zynqmp-rtc.c
133
create mode 100644 target/arm/vec_helper.c
134
54
55
Niek Linnenbank (5):
56
hw/net/allwinner-sun8i-emac: traverse transmit queue using TX_CUR_DESC register value
57
tests/acceptance/boot_linux_console: remove Armbian 19.11.3 bionic test for orangepi-pc machine
58
tests/acceptance/boot_linux_console: change URL for test_arm_orangepi_bionic_20_08
59
tests/acceptance: update sunxi kernel from armbian to 5.10.16
60
tests/acceptance: drop ARMBIAN_ARTIFACTS_CACHED condition for orangepi-pc, cubieboard tests
61
62
Peter Maydell (9):
63
hw/display/pl110: Remove dead code for non-32-bpp surfaces
64
hw/display/pl110: Pull included-once parts of template header into pl110.c
65
hw/display/pl110: Remove use of BITS from pl110_template.h
66
hw/display/pxa2xx_lcd: Remove dead code for non-32-bpp surfaces
67
hw/display/pxa2xx_lcd: Remove dest_width state field
68
hw/display/pxa2xx: Remove use of BITS in pxa2xx_template.h
69
hw/display/pxa2xx: Apply brace-related coding style fixes to template header
70
hw/display/pxa2xx: Apply whitespace-only coding style fixes to template header
71
hw/display/pxa2xx: Inline template header
72
73
Philippe Mathieu-Daudé (1):
74
hw/timer/sse-timer: Propagate eventual error in sse_timer_realize()
75
76
Richard Henderson (8):
77
target/arm: Fix sve_uzp_p vs odd vector lengths
78
target/arm: Fix sve_zip_p vs odd vector lengths
79
target/arm: Fix sve_punpk_p vs odd vector lengths
80
target/arm: Update find_last_active for PREDDESC
81
target/arm: Update BRKA, BRKB, BRKN for PREDDESC
82
target/arm: Update CNTP for PREDDESC
83
target/arm: Update WHILE for PREDDESC
84
target/arm: Update sve reduction vs simd_desc
85
86
docs/system/arm/nuvoton.rst | 2 +-
87
docs/system/arm/xlnx-versal-virt.rst | 1 +
88
hw/arm/smmu-internal.h | 5 +
89
hw/display/pl110_template.h | 120 +-------
90
hw/display/pxa2xx_template.h | 447 ---------------------------
91
include/hw/arm/npcm7xx.h | 13 +-
92
include/hw/arm/xlnx-versal.h | 13 +
93
include/hw/boards.h | 1 +
94
include/hw/misc/npcm7xx_mft.h | 70 +++++
95
include/hw/misc/npcm7xx_pwm.h | 4 +-
96
include/hw/misc/xlnx-versal-xramc.h | 97 ++++++
97
include/sysemu/dma.h | 12 +
98
target/arm/kvm_arm.h | 6 +-
99
accel/kvm/kvm-all.c | 2 +
100
hw/arm/npcm7xx.c | 45 ++-
101
hw/arm/npcm7xx_boards.c | 99 ++++++
102
hw/arm/smmu-common.c | 32 +-
103
hw/arm/smmuv3.c | 58 ++--
104
hw/arm/virt.c | 23 +-
105
hw/arm/xlnx-versal.c | 36 +++
106
hw/display/pl110.c | 123 +++++---
107
hw/display/pxa2xx_lcd.c | 520 ++++++++++++++++++++++++++-----
108
hw/i386/intel_iommu.c | 32 +-
109
hw/misc/npcm7xx_mft.c | 540 +++++++++++++++++++++++++++++++++
110
hw/misc/npcm7xx_pwm.c | 4 +
111
hw/misc/xlnx-versal-xramc.c | 253 +++++++++++++++
112
hw/net/allwinner-sun8i-emac.c | 62 ++--
113
hw/timer/sse-timer.c | 1 +
114
hw/virtio/virtio-iommu.c | 19 +-
115
softmmu/dma-helpers.c | 26 ++
116
target/arm/kvm.c | 4 +-
117
target/arm/sve_helper.c | 107 ++++---
118
target/arm/translate-sve.c | 26 +-
119
tests/qtest/npcm7xx_pwm-test.c | 205 ++++++++++++-
120
hw/arm/trace-events | 24 +-
121
hw/misc/meson.build | 2 +
122
hw/misc/trace-events | 8 +
123
tests/acceptance/boot_linux_console.py | 120 +++-----
124
tests/acceptance/replay_kernel.py | 10 +-
125
39 files changed, 2235 insertions(+), 937 deletions(-)
126
delete mode 100644 hw/display/pxa2xx_template.h
127
create mode 100644 include/hw/misc/npcm7xx_mft.h
128
create mode 100644 include/hw/misc/xlnx-versal-xramc.h
129
create mode 100644 hw/misc/npcm7xx_mft.c
130
create mode 100644 hw/misc/xlnx-versal-xramc.c
131
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
2
3
Initial commit of the ZynqMP RTC device.
3
Add a model of the Xilinx Versal Accelerator RAM (XRAM).
4
4
This is mainly a stub to make firmware happy. The size of
5
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
5
the RAMs can be probed. The interrupt mask logic is
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
modelled but none of the interrups will ever be raised
7
unless injected.
8
9
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Message-id: 20210308224637.2949533-2-edgar.iglesias@gmail.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
13
---
9
hw/timer/Makefile.objs | 1 +
14
include/hw/misc/xlnx-versal-xramc.h | 97 +++++++++++
10
include/hw/timer/xlnx-zynqmp-rtc.h | 84 +++++++++++++++
15
hw/misc/xlnx-versal-xramc.c | 253 ++++++++++++++++++++++++++++
11
hw/timer/xlnx-zynqmp-rtc.c | 214 +++++++++++++++++++++++++++++++++++++
16
hw/misc/meson.build | 1 +
12
3 files changed, 299 insertions(+)
17
3 files changed, 351 insertions(+)
13
create mode 100644 include/hw/timer/xlnx-zynqmp-rtc.h
18
create mode 100644 include/hw/misc/xlnx-versal-xramc.h
14
create mode 100644 hw/timer/xlnx-zynqmp-rtc.c
19
create mode 100644 hw/misc/xlnx-versal-xramc.c
15
20
16
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
21
diff --git a/include/hw/misc/xlnx-versal-xramc.h b/include/hw/misc/xlnx-versal-xramc.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/timer/Makefile.objs
19
+++ b/hw/timer/Makefile.objs
20
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_IMX) += imx_epit.o
21
common-obj-$(CONFIG_IMX) += imx_gpt.o
22
common-obj-$(CONFIG_LM32) += lm32_timer.o
23
common-obj-$(CONFIG_MILKYMIST) += milkymist-sysctl.o
24
+common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp-rtc.o
25
26
obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o
27
obj-$(CONFIG_EXYNOS4) += exynos4210_mct.o
28
diff --git a/include/hw/timer/xlnx-zynqmp-rtc.h b/include/hw/timer/xlnx-zynqmp-rtc.h
29
new file mode 100644
22
new file mode 100644
30
index XXXXXXX..XXXXXXX
23
index XXXXXXX..XXXXXXX
31
--- /dev/null
24
--- /dev/null
32
+++ b/include/hw/timer/xlnx-zynqmp-rtc.h
25
+++ b/include/hw/misc/xlnx-versal-xramc.h
33
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@
34
+/*
27
+/*
35
+ * QEMU model of the Xilinx ZynqMP Real Time Clock (RTC).
28
+ * QEMU model of the Xilinx XRAM Controller.
36
+ *
29
+ *
37
+ * Copyright (c) 2017 Xilinx Inc.
30
+ * Copyright (c) 2021 Xilinx Inc.
38
+ *
31
+ * SPDX-License-Identifier: GPL-2.0-or-later
39
+ * Written-by: Alistair Francis <alistair.francis@xilinx.com>
32
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
40
+ *
41
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
42
+ * of this software and associated documentation files (the "Software"), to deal
43
+ * in the Software without restriction, including without limitation the rights
44
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
45
+ * copies of the Software, and to permit persons to whom the Software is
46
+ * furnished to do so, subject to the following conditions:
47
+ *
48
+ * The above copyright notice and this permission notice shall be included in
49
+ * all copies or substantial portions of the Software.
50
+ *
51
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
54
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
56
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
57
+ * THE SOFTWARE.
58
+ */
33
+ */
59
+
34
+
35
+#ifndef XLNX_VERSAL_XRAMC_H
36
+#define XLNX_VERSAL_XRAMC_H
37
+
38
+#include "hw/sysbus.h"
60
+#include "hw/register.h"
39
+#include "hw/register.h"
61
+
40
+
62
+#define TYPE_XLNX_ZYNQMP_RTC "xlnx-zynmp.rtc"
41
+#define TYPE_XLNX_XRAM_CTRL "xlnx.versal-xramc"
63
+
42
+
64
+#define XLNX_ZYNQMP_RTC(obj) \
43
+#define XLNX_XRAM_CTRL(obj) \
65
+ OBJECT_CHECK(XlnxZynqMPRTC, (obj), TYPE_XLNX_ZYNQMP_RTC)
44
+ OBJECT_CHECK(XlnxXramCtrl, (obj), TYPE_XLNX_XRAM_CTRL)
66
+
45
+
67
+REG32(SET_TIME_WRITE, 0x0)
46
+REG32(XRAM_ERR_CTRL, 0x0)
68
+REG32(SET_TIME_READ, 0x4)
47
+ FIELD(XRAM_ERR_CTRL, UE_RES, 3, 1)
69
+REG32(CALIB_WRITE, 0x8)
48
+ FIELD(XRAM_ERR_CTRL, PWR_ERR_RES, 2, 1)
70
+ FIELD(CALIB_WRITE, FRACTION_EN, 20, 1)
49
+ FIELD(XRAM_ERR_CTRL, PZ_ERR_RES, 1, 1)
71
+ FIELD(CALIB_WRITE, FRACTION_DATA, 16, 4)
50
+ FIELD(XRAM_ERR_CTRL, APB_ERR_RES, 0, 1)
72
+ FIELD(CALIB_WRITE, MAX_TICK, 0, 16)
51
+REG32(XRAM_ISR, 0x4)
73
+REG32(CALIB_READ, 0xc)
52
+ FIELD(XRAM_ISR, INV_APB, 0, 1)
74
+ FIELD(CALIB_READ, FRACTION_EN, 20, 1)
53
+REG32(XRAM_IMR, 0x8)
75
+ FIELD(CALIB_READ, FRACTION_DATA, 16, 4)
54
+ FIELD(XRAM_IMR, INV_APB, 0, 1)
76
+ FIELD(CALIB_READ, MAX_TICK, 0, 16)
55
+REG32(XRAM_IEN, 0xc)
77
+REG32(CURRENT_TIME, 0x10)
56
+ FIELD(XRAM_IEN, INV_APB, 0, 1)
78
+REG32(CURRENT_TICK, 0x14)
57
+REG32(XRAM_IDS, 0x10)
79
+ FIELD(CURRENT_TICK, VALUE, 0, 16)
58
+ FIELD(XRAM_IDS, INV_APB, 0, 1)
80
+REG32(ALARM, 0x18)
59
+REG32(XRAM_ECC_CNTL, 0x14)
81
+REG32(RTC_INT_STATUS, 0x20)
60
+ FIELD(XRAM_ECC_CNTL, FI_MODE, 2, 1)
82
+ FIELD(RTC_INT_STATUS, ALARM, 1, 1)
61
+ FIELD(XRAM_ECC_CNTL, DET_ONLY, 1, 1)
83
+ FIELD(RTC_INT_STATUS, SECONDS, 0, 1)
62
+ FIELD(XRAM_ECC_CNTL, ECC_ON_OFF, 0, 1)
84
+REG32(RTC_INT_MASK, 0x24)
63
+REG32(XRAM_CLR_EXE, 0x18)
85
+ FIELD(RTC_INT_MASK, ALARM, 1, 1)
64
+ FIELD(XRAM_CLR_EXE, MON_7, 7, 1)
86
+ FIELD(RTC_INT_MASK, SECONDS, 0, 1)
65
+ FIELD(XRAM_CLR_EXE, MON_6, 6, 1)
87
+REG32(RTC_INT_EN, 0x28)
66
+ FIELD(XRAM_CLR_EXE, MON_5, 5, 1)
88
+ FIELD(RTC_INT_EN, ALARM, 1, 1)
67
+ FIELD(XRAM_CLR_EXE, MON_4, 4, 1)
89
+ FIELD(RTC_INT_EN, SECONDS, 0, 1)
68
+ FIELD(XRAM_CLR_EXE, MON_3, 3, 1)
90
+REG32(RTC_INT_DIS, 0x2c)
69
+ FIELD(XRAM_CLR_EXE, MON_2, 2, 1)
91
+ FIELD(RTC_INT_DIS, ALARM, 1, 1)
70
+ FIELD(XRAM_CLR_EXE, MON_1, 1, 1)
92
+ FIELD(RTC_INT_DIS, SECONDS, 0, 1)
71
+ FIELD(XRAM_CLR_EXE, MON_0, 0, 1)
93
+REG32(ADDR_ERROR, 0x30)
72
+REG32(XRAM_CE_FFA, 0x1c)
94
+ FIELD(ADDR_ERROR, STATUS, 0, 1)
73
+ FIELD(XRAM_CE_FFA, ADDR, 0, 20)
95
+REG32(ADDR_ERROR_INT_MASK, 0x34)
74
+REG32(XRAM_CE_FFD0, 0x20)
96
+ FIELD(ADDR_ERROR_INT_MASK, MASK, 0, 1)
75
+REG32(XRAM_CE_FFD1, 0x24)
97
+REG32(ADDR_ERROR_INT_EN, 0x38)
76
+REG32(XRAM_CE_FFD2, 0x28)
98
+ FIELD(ADDR_ERROR_INT_EN, MASK, 0, 1)
77
+REG32(XRAM_CE_FFD3, 0x2c)
99
+REG32(ADDR_ERROR_INT_DIS, 0x3c)
78
+REG32(XRAM_CE_FFE, 0x30)
100
+ FIELD(ADDR_ERROR_INT_DIS, MASK, 0, 1)
79
+ FIELD(XRAM_CE_FFE, SYNDROME, 0, 16)
101
+REG32(CONTROL, 0x40)
80
+REG32(XRAM_UE_FFA, 0x34)
102
+ FIELD(CONTROL, BATTERY_DISABLE, 31, 1)
81
+ FIELD(XRAM_UE_FFA, ADDR, 0, 20)
103
+ FIELD(CONTROL, OSC_CNTRL, 24, 4)
82
+REG32(XRAM_UE_FFD0, 0x38)
104
+ FIELD(CONTROL, SLVERR_ENABLE, 0, 1)
83
+REG32(XRAM_UE_FFD1, 0x3c)
105
+REG32(SAFETY_CHK, 0x50)
84
+REG32(XRAM_UE_FFD2, 0x40)
106
+
85
+REG32(XRAM_UE_FFD3, 0x44)
107
+#define XLNX_ZYNQMP_RTC_R_MAX (R_SAFETY_CHK + 1)
86
+REG32(XRAM_UE_FFE, 0x48)
108
+
87
+ FIELD(XRAM_UE_FFE, SYNDROME, 0, 16)
109
+typedef struct XlnxZynqMPRTC {
88
+REG32(XRAM_FI_D0, 0x4c)
89
+REG32(XRAM_FI_D1, 0x50)
90
+REG32(XRAM_FI_D2, 0x54)
91
+REG32(XRAM_FI_D3, 0x58)
92
+REG32(XRAM_FI_SY, 0x5c)
93
+ FIELD(XRAM_FI_SY, DATA, 0, 16)
94
+REG32(XRAM_RMW_UE_FFA, 0x70)
95
+ FIELD(XRAM_RMW_UE_FFA, ADDR, 0, 20)
96
+REG32(XRAM_FI_CNTR, 0x74)
97
+ FIELD(XRAM_FI_CNTR, COUNT, 0, 24)
98
+REG32(XRAM_IMP, 0x80)
99
+ FIELD(XRAM_IMP, SIZE, 0, 4)
100
+REG32(XRAM_PRDY_DBG, 0x84)
101
+ FIELD(XRAM_PRDY_DBG, ISLAND3, 12, 4)
102
+ FIELD(XRAM_PRDY_DBG, ISLAND2, 8, 4)
103
+ FIELD(XRAM_PRDY_DBG, ISLAND1, 4, 4)
104
+ FIELD(XRAM_PRDY_DBG, ISLAND0, 0, 4)
105
+REG32(XRAM_SAFETY_CHK, 0xff8)
106
+
107
+#define XRAM_CTRL_R_MAX (R_XRAM_SAFETY_CHK + 1)
108
+
109
+typedef struct XlnxXramCtrl {
110
+ SysBusDevice parent_obj;
110
+ SysBusDevice parent_obj;
111
+ MemoryRegion iomem;
111
+ MemoryRegion ram;
112
+ qemu_irq irq_rtc_int;
112
+ qemu_irq irq;
113
+ qemu_irq irq_addr_error_int;
113
+
114
+
114
+ struct {
115
+ uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX];
115
+ uint64_t size;
116
+ RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX];
116
+ unsigned int encoded_size;
117
+} XlnxZynqMPRTC;
117
+ } cfg;
118
diff --git a/hw/timer/xlnx-zynqmp-rtc.c b/hw/timer/xlnx-zynqmp-rtc.c
118
+
119
+ RegisterInfoArray *reg_array;
120
+ uint32_t regs[XRAM_CTRL_R_MAX];
121
+ RegisterInfo regs_info[XRAM_CTRL_R_MAX];
122
+} XlnxXramCtrl;
123
+#endif
124
diff --git a/hw/misc/xlnx-versal-xramc.c b/hw/misc/xlnx-versal-xramc.c
119
new file mode 100644
125
new file mode 100644
120
index XXXXXXX..XXXXXXX
126
index XXXXXXX..XXXXXXX
121
--- /dev/null
127
--- /dev/null
122
+++ b/hw/timer/xlnx-zynqmp-rtc.c
128
+++ b/hw/misc/xlnx-versal-xramc.c
123
@@ -XXX,XX +XXX,XX @@
129
@@ -XXX,XX +XXX,XX @@
124
+/*
130
+/*
125
+ * QEMU model of the Xilinx ZynqMP Real Time Clock (RTC).
131
+ * QEMU model of the Xilinx XRAM Controller.
126
+ *
132
+ *
127
+ * Copyright (c) 2017 Xilinx Inc.
133
+ * Copyright (c) 2021 Xilinx Inc.
128
+ *
134
+ * SPDX-License-Identifier: GPL-2.0-or-later
129
+ * Written-by: Alistair Francis <alistair.francis@xilinx.com>
135
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
130
+ *
131
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
132
+ * of this software and associated documentation files (the "Software"), to deal
133
+ * in the Software without restriction, including without limitation the rights
134
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
135
+ * copies of the Software, and to permit persons to whom the Software is
136
+ * furnished to do so, subject to the following conditions:
137
+ *
138
+ * The above copyright notice and this permission notice shall be included in
139
+ * all copies or substantial portions of the Software.
140
+ *
141
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
142
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
143
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
144
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
145
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
146
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
147
+ * THE SOFTWARE.
148
+ */
136
+ */
149
+
137
+
150
+#include "qemu/osdep.h"
138
+#include "qemu/osdep.h"
139
+#include "qemu/units.h"
140
+#include "qapi/error.h"
141
+#include "migration/vmstate.h"
151
+#include "hw/sysbus.h"
142
+#include "hw/sysbus.h"
152
+#include "hw/register.h"
143
+#include "hw/register.h"
153
+#include "qemu/bitops.h"
144
+#include "hw/qdev-properties.h"
154
+#include "qemu/log.h"
145
+#include "hw/irq.h"
155
+#include "hw/timer/xlnx-zynqmp-rtc.h"
146
+#include "hw/misc/xlnx-versal-xramc.h"
156
+
147
+
157
+#ifndef XLNX_ZYNQMP_RTC_ERR_DEBUG
148
+#ifndef XLNX_XRAM_CTRL_ERR_DEBUG
158
+#define XLNX_ZYNQMP_RTC_ERR_DEBUG 0
149
+#define XLNX_XRAM_CTRL_ERR_DEBUG 0
159
+#endif
150
+#endif
160
+
151
+
161
+static void rtc_int_update_irq(XlnxZynqMPRTC *s)
152
+static void xram_update_irq(XlnxXramCtrl *s)
162
+{
153
+{
163
+ bool pending = s->regs[R_RTC_INT_STATUS] & ~s->regs[R_RTC_INT_MASK];
154
+ bool pending = s->regs[R_XRAM_ISR] & ~s->regs[R_XRAM_IMR];
164
+ qemu_set_irq(s->irq_rtc_int, pending);
155
+ qemu_set_irq(s->irq, pending);
165
+}
156
+}
166
+
157
+
167
+static void addr_error_int_update_irq(XlnxZynqMPRTC *s)
158
+static void xram_isr_postw(RegisterInfo *reg, uint64_t val64)
168
+{
159
+{
169
+ bool pending = s->regs[R_ADDR_ERROR] & ~s->regs[R_ADDR_ERROR_INT_MASK];
160
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
170
+ qemu_set_irq(s->irq_addr_error_int, pending);
161
+ xram_update_irq(s);
171
+}
162
+}
172
+
163
+
173
+static void rtc_int_status_postw(RegisterInfo *reg, uint64_t val64)
164
+static uint64_t xram_ien_prew(RegisterInfo *reg, uint64_t val64)
174
+{
165
+{
175
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
166
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
176
+ rtc_int_update_irq(s);
167
+ uint32_t val = val64;
177
+}
168
+
178
+
169
+ s->regs[R_XRAM_IMR] &= ~val;
179
+static uint64_t rtc_int_en_prew(RegisterInfo *reg, uint64_t val64)
170
+ xram_update_irq(s);
180
+{
181
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
182
+
183
+ s->regs[R_RTC_INT_MASK] &= (uint32_t) ~val64;
184
+ rtc_int_update_irq(s);
185
+ return 0;
171
+ return 0;
186
+}
172
+}
187
+
173
+
188
+static uint64_t rtc_int_dis_prew(RegisterInfo *reg, uint64_t val64)
174
+static uint64_t xram_ids_prew(RegisterInfo *reg, uint64_t val64)
189
+{
175
+{
190
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
176
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
191
+
177
+ uint32_t val = val64;
192
+ s->regs[R_RTC_INT_MASK] |= (uint32_t) val64;
178
+
193
+ rtc_int_update_irq(s);
179
+ s->regs[R_XRAM_IMR] |= val;
180
+ xram_update_irq(s);
194
+ return 0;
181
+ return 0;
195
+}
182
+}
196
+
183
+
197
+static void addr_error_postw(RegisterInfo *reg, uint64_t val64)
184
+static const RegisterAccessInfo xram_ctrl_regs_info[] = {
198
+{
185
+ { .name = "XRAM_ERR_CTRL", .addr = A_XRAM_ERR_CTRL,
199
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
186
+ .reset = 0xf,
200
+ addr_error_int_update_irq(s);
187
+ .rsvd = 0xfffffff0,
201
+}
188
+ },{ .name = "XRAM_ISR", .addr = A_XRAM_ISR,
202
+
189
+ .rsvd = 0xfffff800,
203
+static uint64_t addr_error_int_en_prew(RegisterInfo *reg, uint64_t val64)
190
+ .w1c = 0x7ff,
204
+{
191
+ .post_write = xram_isr_postw,
205
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
192
+ },{ .name = "XRAM_IMR", .addr = A_XRAM_IMR,
206
+
193
+ .reset = 0x7ff,
207
+ s->regs[R_ADDR_ERROR_INT_MASK] &= (uint32_t) ~val64;
194
+ .rsvd = 0xfffff800,
208
+ addr_error_int_update_irq(s);
195
+ .ro = 0x7ff,
209
+ return 0;
196
+ },{ .name = "XRAM_IEN", .addr = A_XRAM_IEN,
210
+}
197
+ .rsvd = 0xfffff800,
211
+
198
+ .pre_write = xram_ien_prew,
212
+static uint64_t addr_error_int_dis_prew(RegisterInfo *reg, uint64_t val64)
199
+ },{ .name = "XRAM_IDS", .addr = A_XRAM_IDS,
213
+{
200
+ .rsvd = 0xfffff800,
214
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
201
+ .pre_write = xram_ids_prew,
215
+
202
+ },{ .name = "XRAM_ECC_CNTL", .addr = A_XRAM_ECC_CNTL,
216
+ s->regs[R_ADDR_ERROR_INT_MASK] |= (uint32_t) val64;
203
+ .rsvd = 0xfffffff8,
217
+ addr_error_int_update_irq(s);
204
+ },{ .name = "XRAM_CLR_EXE", .addr = A_XRAM_CLR_EXE,
218
+ return 0;
205
+ .rsvd = 0xffffff00,
219
+}
206
+ },{ .name = "XRAM_CE_FFA", .addr = A_XRAM_CE_FFA,
220
+
207
+ .rsvd = 0xfff00000,
221
+static const RegisterAccessInfo rtc_regs_info[] = {
208
+ .ro = 0xfffff,
222
+ { .name = "SET_TIME_WRITE", .addr = A_SET_TIME_WRITE,
209
+ },{ .name = "XRAM_CE_FFD0", .addr = A_XRAM_CE_FFD0,
223
+ },{ .name = "SET_TIME_READ", .addr = A_SET_TIME_READ,
210
+ .ro = 0xffffffff,
224
+ .ro = 0xffffffff,
211
+ },{ .name = "XRAM_CE_FFD1", .addr = A_XRAM_CE_FFD1,
225
+ },{ .name = "CALIB_WRITE", .addr = A_CALIB_WRITE,
212
+ .ro = 0xffffffff,
226
+ },{ .name = "CALIB_READ", .addr = A_CALIB_READ,
213
+ },{ .name = "XRAM_CE_FFD2", .addr = A_XRAM_CE_FFD2,
227
+ .ro = 0x1fffff,
214
+ .ro = 0xffffffff,
228
+ },{ .name = "CURRENT_TIME", .addr = A_CURRENT_TIME,
215
+ },{ .name = "XRAM_CE_FFD3", .addr = A_XRAM_CE_FFD3,
229
+ .ro = 0xffffffff,
216
+ .ro = 0xffffffff,
230
+ },{ .name = "CURRENT_TICK", .addr = A_CURRENT_TICK,
217
+ },{ .name = "XRAM_CE_FFE", .addr = A_XRAM_CE_FFE,
218
+ .rsvd = 0xffff0000,
231
+ .ro = 0xffff,
219
+ .ro = 0xffff,
232
+ },{ .name = "ALARM", .addr = A_ALARM,
220
+ },{ .name = "XRAM_UE_FFA", .addr = A_XRAM_UE_FFA,
233
+ },{ .name = "RTC_INT_STATUS", .addr = A_RTC_INT_STATUS,
221
+ .rsvd = 0xfff00000,
234
+ .w1c = 0x3,
222
+ .ro = 0xfffff,
235
+ .post_write = rtc_int_status_postw,
223
+ },{ .name = "XRAM_UE_FFD0", .addr = A_XRAM_UE_FFD0,
236
+ },{ .name = "RTC_INT_MASK", .addr = A_RTC_INT_MASK,
224
+ .ro = 0xffffffff,
237
+ .reset = 0x3,
225
+ },{ .name = "XRAM_UE_FFD1", .addr = A_XRAM_UE_FFD1,
238
+ .ro = 0x3,
226
+ .ro = 0xffffffff,
239
+ },{ .name = "RTC_INT_EN", .addr = A_RTC_INT_EN,
227
+ },{ .name = "XRAM_UE_FFD2", .addr = A_XRAM_UE_FFD2,
240
+ .pre_write = rtc_int_en_prew,
228
+ .ro = 0xffffffff,
241
+ },{ .name = "RTC_INT_DIS", .addr = A_RTC_INT_DIS,
229
+ },{ .name = "XRAM_UE_FFD3", .addr = A_XRAM_UE_FFD3,
242
+ .pre_write = rtc_int_dis_prew,
230
+ .ro = 0xffffffff,
243
+ },{ .name = "ADDR_ERROR", .addr = A_ADDR_ERROR,
231
+ },{ .name = "XRAM_UE_FFE", .addr = A_XRAM_UE_FFE,
244
+ .w1c = 0x1,
232
+ .rsvd = 0xffff0000,
245
+ .post_write = addr_error_postw,
233
+ .ro = 0xffff,
246
+ },{ .name = "ADDR_ERROR_INT_MASK", .addr = A_ADDR_ERROR_INT_MASK,
234
+ },{ .name = "XRAM_FI_D0", .addr = A_XRAM_FI_D0,
247
+ .reset = 0x1,
235
+ },{ .name = "XRAM_FI_D1", .addr = A_XRAM_FI_D1,
248
+ .ro = 0x1,
236
+ },{ .name = "XRAM_FI_D2", .addr = A_XRAM_FI_D2,
249
+ },{ .name = "ADDR_ERROR_INT_EN", .addr = A_ADDR_ERROR_INT_EN,
237
+ },{ .name = "XRAM_FI_D3", .addr = A_XRAM_FI_D3,
250
+ .pre_write = addr_error_int_en_prew,
238
+ },{ .name = "XRAM_FI_SY", .addr = A_XRAM_FI_SY,
251
+ },{ .name = "ADDR_ERROR_INT_DIS", .addr = A_ADDR_ERROR_INT_DIS,
239
+ .rsvd = 0xffff0000,
252
+ .pre_write = addr_error_int_dis_prew,
240
+ },{ .name = "XRAM_RMW_UE_FFA", .addr = A_XRAM_RMW_UE_FFA,
253
+ },{ .name = "CONTROL", .addr = A_CONTROL,
241
+ .rsvd = 0xfff00000,
254
+ .reset = 0x1000000,
242
+ .ro = 0xfffff,
255
+ .rsvd = 0x70fffffe,
243
+ },{ .name = "XRAM_FI_CNTR", .addr = A_XRAM_FI_CNTR,
256
+ },{ .name = "SAFETY_CHK", .addr = A_SAFETY_CHK,
244
+ .rsvd = 0xff000000,
245
+ },{ .name = "XRAM_IMP", .addr = A_XRAM_IMP,
246
+ .reset = 0x4,
247
+ .rsvd = 0xfffffff0,
248
+ .ro = 0xf,
249
+ },{ .name = "XRAM_PRDY_DBG", .addr = A_XRAM_PRDY_DBG,
250
+ .reset = 0xffff,
251
+ .rsvd = 0xffff0000,
252
+ .ro = 0xffff,
253
+ },{ .name = "XRAM_SAFETY_CHK", .addr = A_XRAM_SAFETY_CHK,
257
+ }
254
+ }
258
+};
255
+};
259
+
256
+
260
+static void rtc_reset(DeviceState *dev)
257
+static void xram_ctrl_reset_enter(Object *obj, ResetType type)
261
+{
258
+{
262
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(dev);
259
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
263
+ unsigned int i;
260
+ unsigned int i;
264
+
261
+
265
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
262
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
266
+ register_reset(&s->regs_info[i]);
263
+ register_reset(&s->regs_info[i]);
267
+ }
264
+ }
268
+
265
+
269
+ rtc_int_update_irq(s);
266
+ ARRAY_FIELD_DP32(s->regs, XRAM_IMP, SIZE, s->cfg.encoded_size);
270
+ addr_error_int_update_irq(s);
267
+}
271
+}
268
+
272
+
269
+static void xram_ctrl_reset_hold(Object *obj)
273
+static const MemoryRegionOps rtc_ops = {
270
+{
271
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
272
+
273
+ xram_update_irq(s);
274
+}
275
+
276
+static const MemoryRegionOps xram_ctrl_ops = {
274
+ .read = register_read_memory,
277
+ .read = register_read_memory,
275
+ .write = register_write_memory,
278
+ .write = register_write_memory,
276
+ .endianness = DEVICE_LITTLE_ENDIAN,
279
+ .endianness = DEVICE_LITTLE_ENDIAN,
277
+ .valid = {
280
+ .valid = {
278
+ .min_access_size = 4,
281
+ .min_access_size = 4,
279
+ .max_access_size = 4,
282
+ .max_access_size = 4,
280
+ },
283
+ },
281
+};
284
+};
282
+
285
+
283
+static void rtc_init(Object *obj)
286
+static void xram_ctrl_realize(DeviceState *dev, Error **errp)
284
+{
287
+{
285
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(obj);
288
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
289
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(dev);
290
+
291
+ switch (s->cfg.size) {
292
+ case 64 * KiB:
293
+ s->cfg.encoded_size = 0;
294
+ break;
295
+ case 128 * KiB:
296
+ s->cfg.encoded_size = 1;
297
+ break;
298
+ case 256 * KiB:
299
+ s->cfg.encoded_size = 2;
300
+ break;
301
+ case 512 * KiB:
302
+ s->cfg.encoded_size = 3;
303
+ break;
304
+ case 1 * MiB:
305
+ s->cfg.encoded_size = 4;
306
+ break;
307
+ default:
308
+ error_setg(errp, "Unsupported XRAM size %" PRId64, s->cfg.size);
309
+ return;
310
+ }
311
+
312
+ memory_region_init_ram(&s->ram, OBJECT(s),
313
+ object_get_canonical_path_component(OBJECT(s)),
314
+ s->cfg.size, &error_fatal);
315
+ sysbus_init_mmio(sbd, &s->ram);
316
+}
317
+
318
+static void xram_ctrl_init(Object *obj)
319
+{
320
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
286
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
321
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
287
+ RegisterInfoArray *reg_array;
322
+
288
+
323
+ s->reg_array =
289
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_RTC,
324
+ register_init_block32(DEVICE(obj), xram_ctrl_regs_info,
290
+ XLNX_ZYNQMP_RTC_R_MAX * 4);
325
+ ARRAY_SIZE(xram_ctrl_regs_info),
291
+ reg_array =
292
+ register_init_block32(DEVICE(obj), rtc_regs_info,
293
+ ARRAY_SIZE(rtc_regs_info),
294
+ s->regs_info, s->regs,
326
+ s->regs_info, s->regs,
295
+ &rtc_ops,
327
+ &xram_ctrl_ops,
296
+ XLNX_ZYNQMP_RTC_ERR_DEBUG,
328
+ XLNX_XRAM_CTRL_ERR_DEBUG,
297
+ XLNX_ZYNQMP_RTC_R_MAX * 4);
329
+ XRAM_CTRL_R_MAX * 4);
298
+ memory_region_add_subregion(&s->iomem,
330
+ sysbus_init_mmio(sbd, &s->reg_array->mem);
299
+ 0x0,
331
+ sysbus_init_irq(sbd, &s->irq);
300
+ &reg_array->mem);
332
+}
301
+ sysbus_init_mmio(sbd, &s->iomem);
333
+
302
+ sysbus_init_irq(sbd, &s->irq_rtc_int);
334
+static void xram_ctrl_finalize(Object *obj)
303
+ sysbus_init_irq(sbd, &s->irq_addr_error_int);
335
+{
304
+}
336
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
305
+
337
+ register_finalize_block(s->reg_array);
306
+static const VMStateDescription vmstate_rtc = {
338
+}
307
+ .name = TYPE_XLNX_ZYNQMP_RTC,
339
+
340
+static const VMStateDescription vmstate_xram_ctrl = {
341
+ .name = TYPE_XLNX_XRAM_CTRL,
308
+ .version_id = 1,
342
+ .version_id = 1,
309
+ .minimum_version_id = 1,
343
+ .minimum_version_id = 1,
310
+ .fields = (VMStateField[]) {
344
+ .fields = (VMStateField[]) {
311
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPRTC, XLNX_ZYNQMP_RTC_R_MAX),
345
+ VMSTATE_UINT32_ARRAY(regs, XlnxXramCtrl, XRAM_CTRL_R_MAX),
312
+ VMSTATE_END_OF_LIST(),
346
+ VMSTATE_END_OF_LIST(),
313
+ }
347
+ }
314
+};
348
+};
315
+
349
+
316
+static void rtc_class_init(ObjectClass *klass, void *data)
350
+static Property xram_ctrl_properties[] = {
317
+{
351
+ DEFINE_PROP_UINT64("size", XlnxXramCtrl, cfg.size, 1 * MiB),
352
+ DEFINE_PROP_END_OF_LIST(),
353
+};
354
+
355
+static void xram_ctrl_class_init(ObjectClass *klass, void *data)
356
+{
357
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
318
+ DeviceClass *dc = DEVICE_CLASS(klass);
358
+ DeviceClass *dc = DEVICE_CLASS(klass);
319
+
359
+
320
+ dc->reset = rtc_reset;
360
+ dc->realize = xram_ctrl_realize;
321
+ dc->vmsd = &vmstate_rtc;
361
+ dc->vmsd = &vmstate_xram_ctrl;
322
+}
362
+ device_class_set_props(dc, xram_ctrl_properties);
323
+
363
+
324
+static const TypeInfo rtc_info = {
364
+ rc->phases.enter = xram_ctrl_reset_enter;
325
+ .name = TYPE_XLNX_ZYNQMP_RTC,
365
+ rc->phases.hold = xram_ctrl_reset_hold;
326
+ .parent = TYPE_SYS_BUS_DEVICE,
366
+}
327
+ .instance_size = sizeof(XlnxZynqMPRTC),
367
+
328
+ .class_init = rtc_class_init,
368
+static const TypeInfo xram_ctrl_info = {
329
+ .instance_init = rtc_init,
369
+ .name = TYPE_XLNX_XRAM_CTRL,
330
+};
370
+ .parent = TYPE_SYS_BUS_DEVICE,
331
+
371
+ .instance_size = sizeof(XlnxXramCtrl),
332
+static void rtc_register_types(void)
372
+ .class_init = xram_ctrl_class_init,
333
+{
373
+ .instance_init = xram_ctrl_init,
334
+ type_register_static(&rtc_info);
374
+ .instance_finalize = xram_ctrl_finalize,
335
+}
375
+};
336
+
376
+
337
+type_init(rtc_register_types)
377
+static void xram_ctrl_register_types(void)
378
+{
379
+ type_register_static(&xram_ctrl_info);
380
+}
381
+
382
+type_init(xram_ctrl_register_types)
383
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
384
index XXXXXXX..XXXXXXX 100644
385
--- a/hw/misc/meson.build
386
+++ b/hw/misc/meson.build
387
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files(
388
))
389
softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c'))
390
softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c', 'zynq-xadc.c'))
391
+softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-xramc.c'))
392
softmmu_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c'))
393
softmmu_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c'))
394
softmmu_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c'))
338
--
395
--
339
2.16.2
396
2.20.1
340
397
341
398
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Connect the support for the Versal Accelerator RAMs (XRAMs).
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
5
Message-id: 20180228193125.20577-5-richard.henderson@linaro.org
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
6
Acked-by: Alistair Francis <alistair.francis@wdc.com>
7
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Message-id: 20210308224637.2949533-3-edgar.iglesias@gmail.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/Makefile.objs | 2 +-
11
docs/system/arm/xlnx-versal-virt.rst | 1 +
9
target/arm/helper.h | 4 ++
12
include/hw/arm/xlnx-versal.h | 13 ++++++++++
10
target/arm/translate-a64.c | 84 ++++++++++++++++++++++++++++++++++
13
hw/arm/xlnx-versal.c | 36 ++++++++++++++++++++++++++++
11
target/arm/vec_helper.c | 109 +++++++++++++++++++++++++++++++++++++++++++++
14
3 files changed, 50 insertions(+)
12
4 files changed, 198 insertions(+), 1 deletion(-)
13
create mode 100644 target/arm/vec_helper.c
14
15
15
diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs
16
diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/Makefile.objs
18
--- a/docs/system/arm/xlnx-versal-virt.rst
18
+++ b/target/arm/Makefile.objs
19
+++ b/docs/system/arm/xlnx-versal-virt.rst
19
@@ -XXX,XX +XXX,XX @@ obj-$(call land,$(CONFIG_KVM),$(call lnot,$(TARGET_AARCH64))) += kvm32.o
20
@@ -XXX,XX +XXX,XX @@ Implemented devices:
20
obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o
21
- 8 ADMA (Xilinx zDMA) channels
21
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
22
- 2 SD Controllers
22
obj-y += translate.o op_helper.o helper.o cpu.o
23
- OCM (256KB of On Chip Memory)
23
-obj-y += neon_helper.o iwmmxt_helper.o
24
+- XRAM (4MB of on chip Accelerator RAM)
24
+obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o
25
- DDR memory
25
obj-y += gdbstub.o
26
26
obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o
27
QEMU does not yet model any other devices, including the PL and the AI Engine.
27
obj-y += crypto_helper.o
28
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
28
diff --git a/target/arm/helper.h b/target/arm/helper.h
29
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/helper.h
30
--- a/include/hw/arm/xlnx-versal.h
31
+++ b/target/arm/helper.h
31
+++ b/include/hw/arm/xlnx-versal.h
32
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_1(neon_rbit_u8, TCG_CALL_NO_RWG_SE, i32, i32)
32
@@ -XXX,XX +XXX,XX @@
33
33
34
DEF_HELPER_3(neon_qdmulh_s16, i32, env, i32, i32)
34
#include "hw/sysbus.h"
35
DEF_HELPER_3(neon_qrdmulh_s16, i32, env, i32, i32)
35
#include "hw/arm/boot.h"
36
+DEF_HELPER_4(neon_qrdmlah_s16, i32, env, i32, i32, i32)
36
+#include "hw/or-irq.h"
37
+DEF_HELPER_4(neon_qrdmlsh_s16, i32, env, i32, i32, i32)
37
#include "hw/sd/sdhci.h"
38
DEF_HELPER_3(neon_qdmulh_s32, i32, env, i32, i32)
38
#include "hw/intc/arm_gicv3.h"
39
DEF_HELPER_3(neon_qrdmulh_s32, i32, env, i32, i32)
39
#include "hw/char/pl011.h"
40
+DEF_HELPER_4(neon_qrdmlah_s32, i32, env, s32, s32, s32)
40
@@ -XXX,XX +XXX,XX @@
41
+DEF_HELPER_4(neon_qrdmlsh_s32, i32, env, s32, s32, s32)
41
#include "hw/rtc/xlnx-zynqmp-rtc.h"
42
42
#include "qom/object.h"
43
DEF_HELPER_1(neon_narrow_u8, i32, i64)
43
#include "hw/usb/xlnx-usb-subsystem.h"
44
DEF_HELPER_1(neon_narrow_u16, i32, i64)
44
+#include "hw/misc/xlnx-versal-xramc.h"
45
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
45
46
#define TYPE_XLNX_VERSAL "xlnx-versal"
47
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
48
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
49
#define XLNX_VERSAL_NR_GEMS 2
50
#define XLNX_VERSAL_NR_ADMAS 8
51
#define XLNX_VERSAL_NR_SDS 2
52
+#define XLNX_VERSAL_NR_XRAM 4
53
#define XLNX_VERSAL_NR_IRQS 192
54
55
struct Versal {
56
@@ -XXX,XX +XXX,XX @@ struct Versal {
57
XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
58
VersalUsb2 usb;
59
} iou;
60
+
61
+ struct {
62
+ qemu_or_irq irq_orgate;
63
+ XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
64
+ } xram;
65
} lpd;
66
67
/* The Platform Management Controller subsystem. */
68
@@ -XXX,XX +XXX,XX @@ struct Versal {
69
#define VERSAL_GEM1_IRQ_0 58
70
#define VERSAL_GEM1_WAKE_IRQ_0 59
71
#define VERSAL_ADMA_IRQ_0 60
72
+#define VERSAL_XRAM_IRQ_0 79
73
#define VERSAL_RTC_APB_ERR_IRQ 121
74
#define VERSAL_SD0_IRQ_0 126
75
#define VERSAL_RTC_ALARM_IRQ 142
76
@@ -XXX,XX +XXX,XX @@ struct Versal {
77
#define MM_OCM 0xfffc0000U
78
#define MM_OCM_SIZE 0x40000
79
80
+#define MM_XRAM 0xfe800000
81
+#define MM_XRAMC 0xff8e0000
82
+#define MM_XRAMC_SIZE 0x10000
83
+
84
#define MM_USB2_CTRL_REGS 0xFF9D0000
85
#define MM_USB2_CTRL_REGS_SIZE 0x10000
86
87
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
46
index XXXXXXX..XXXXXXX 100644
88
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/translate-a64.c
89
--- a/hw/arm/xlnx-versal.c
48
+++ b/target/arm/translate-a64.c
90
+++ b/hw/arm/xlnx-versal.c
49
@@ -XXX,XX +XXX,XX @@ static void disas_simd_scalar_three_reg_same_fp16(DisasContext *s,
91
@@ -XXX,XX +XXX,XX @@
50
tcg_temp_free_ptr(fpst);
92
*/
93
94
#include "qemu/osdep.h"
95
+#include "qemu/units.h"
96
#include "qapi/error.h"
97
#include "qemu/log.h"
98
#include "qemu/module.h"
99
@@ -XXX,XX +XXX,XX @@ static void versal_create_rtc(Versal *s, qemu_irq *pic)
100
sysbus_connect_irq(sbd, 1, pic[VERSAL_RTC_APB_ERR_IRQ]);
51
}
101
}
52
102
53
+/* AdvSIMD scalar three same extra
103
+static void versal_create_xrams(Versal *s, qemu_irq *pic)
54
+ * 31 30 29 28 24 23 22 21 20 16 15 14 11 10 9 5 4 0
55
+ * +-----+---+-----------+------+---+------+---+--------+---+----+----+
56
+ * | 0 1 | U | 1 1 1 1 0 | size | 0 | Rm | 1 | opcode | 1 | Rn | Rd |
57
+ * +-----+---+-----------+------+---+------+---+--------+---+----+----+
58
+ */
59
+static void disas_simd_scalar_three_reg_same_extra(DisasContext *s,
60
+ uint32_t insn)
61
+{
104
+{
62
+ int rd = extract32(insn, 0, 5);
105
+ int nr_xrams = ARRAY_SIZE(s->lpd.xram.ctrl);
63
+ int rn = extract32(insn, 5, 5);
106
+ DeviceState *orgate;
64
+ int opcode = extract32(insn, 11, 4);
107
+ int i;
65
+ int rm = extract32(insn, 16, 5);
66
+ int size = extract32(insn, 22, 2);
67
+ bool u = extract32(insn, 29, 1);
68
+ TCGv_i32 ele1, ele2, ele3;
69
+ TCGv_i64 res;
70
+ int feature;
71
+
108
+
72
+ switch (u * 16 + opcode) {
109
+ /* XRAM IRQs get ORed into a single line. */
73
+ case 0x10: /* SQRDMLAH (vector) */
110
+ object_initialize_child(OBJECT(s), "xram-irq-orgate",
74
+ case 0x11: /* SQRDMLSH (vector) */
111
+ &s->lpd.xram.irq_orgate, TYPE_OR_IRQ);
75
+ if (size != 1 && size != 2) {
112
+ orgate = DEVICE(&s->lpd.xram.irq_orgate);
76
+ unallocated_encoding(s);
113
+ object_property_set_int(OBJECT(orgate),
77
+ return;
114
+ "num-lines", nr_xrams, &error_fatal);
78
+ }
115
+ qdev_realize(orgate, NULL, &error_fatal);
79
+ feature = ARM_FEATURE_V8_RDM;
116
+ qdev_connect_gpio_out(orgate, 0, pic[VERSAL_XRAM_IRQ_0]);
80
+ break;
117
+
81
+ default:
118
+ for (i = 0; i < ARRAY_SIZE(s->lpd.xram.ctrl); i++) {
82
+ unallocated_encoding(s);
119
+ SysBusDevice *sbd;
83
+ return;
120
+ MemoryRegion *mr;
121
+
122
+ object_initialize_child(OBJECT(s), "xram[*]", &s->lpd.xram.ctrl[i],
123
+ TYPE_XLNX_XRAM_CTRL);
124
+ sbd = SYS_BUS_DEVICE(&s->lpd.xram.ctrl[i]);
125
+ sysbus_realize(sbd, &error_fatal);
126
+
127
+ mr = sysbus_mmio_get_region(sbd, 0);
128
+ memory_region_add_subregion(&s->mr_ps,
129
+ MM_XRAMC + i * MM_XRAMC_SIZE, mr);
130
+ mr = sysbus_mmio_get_region(sbd, 1);
131
+ memory_region_add_subregion(&s->mr_ps, MM_XRAM + i * MiB, mr);
132
+
133
+ sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(orgate, i));
84
+ }
134
+ }
85
+ if (!arm_dc_feature(s, feature)) {
86
+ unallocated_encoding(s);
87
+ return;
88
+ }
89
+ if (!fp_access_check(s)) {
90
+ return;
91
+ }
92
+
93
+ /* Do a single operation on the lowest element in the vector.
94
+ * We use the standard Neon helpers and rely on 0 OP 0 == 0
95
+ * with no side effects for all these operations.
96
+ * OPTME: special-purpose helpers would avoid doing some
97
+ * unnecessary work in the helper for the 16 bit cases.
98
+ */
99
+ ele1 = tcg_temp_new_i32();
100
+ ele2 = tcg_temp_new_i32();
101
+ ele3 = tcg_temp_new_i32();
102
+
103
+ read_vec_element_i32(s, ele1, rn, 0, size);
104
+ read_vec_element_i32(s, ele2, rm, 0, size);
105
+ read_vec_element_i32(s, ele3, rd, 0, size);
106
+
107
+ switch (opcode) {
108
+ case 0x0: /* SQRDMLAH */
109
+ if (size == 1) {
110
+ gen_helper_neon_qrdmlah_s16(ele3, cpu_env, ele1, ele2, ele3);
111
+ } else {
112
+ gen_helper_neon_qrdmlah_s32(ele3, cpu_env, ele1, ele2, ele3);
113
+ }
114
+ break;
115
+ case 0x1: /* SQRDMLSH */
116
+ if (size == 1) {
117
+ gen_helper_neon_qrdmlsh_s16(ele3, cpu_env, ele1, ele2, ele3);
118
+ } else {
119
+ gen_helper_neon_qrdmlsh_s32(ele3, cpu_env, ele1, ele2, ele3);
120
+ }
121
+ break;
122
+ default:
123
+ g_assert_not_reached();
124
+ }
125
+ tcg_temp_free_i32(ele1);
126
+ tcg_temp_free_i32(ele2);
127
+
128
+ res = tcg_temp_new_i64();
129
+ tcg_gen_extu_i32_i64(res, ele3);
130
+ tcg_temp_free_i32(ele3);
131
+
132
+ write_fp_dreg(s, rd, res);
133
+ tcg_temp_free_i64(res);
134
+}
135
+}
135
+
136
+
136
static void handle_2misc_64(DisasContext *s, int opcode, bool u,
137
/* This takes the board allocated linear DDR memory and creates aliases
137
TCGv_i64 tcg_rd, TCGv_i64 tcg_rn,
138
* for each split DDR range/aperture on the Versal address map.
138
TCGv_i32 tcg_rmode, TCGv_ptr tcg_fpstatus)
139
*/
139
@@ -XXX,XX +XXX,XX @@ static const AArch64DecodeTable data_proc_simd[] = {
140
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
140
{ 0x0e000800, 0xbf208c00, disas_simd_zip_trn },
141
versal_create_admas(s, pic);
141
{ 0x2e000000, 0xbf208400, disas_simd_ext },
142
versal_create_sds(s, pic);
142
{ 0x5e200400, 0xdf200400, disas_simd_scalar_three_reg_same },
143
versal_create_rtc(s, pic);
143
+ { 0x5e008400, 0xdf208400, disas_simd_scalar_three_reg_same_extra },
144
+ versal_create_xrams(s, pic);
144
{ 0x5e200000, 0xdf200c00, disas_simd_scalar_three_reg_diff },
145
versal_map_ddr(s);
145
{ 0x5e200800, 0xdf3e0c00, disas_simd_scalar_two_reg_misc },
146
versal_unimp(s);
146
{ 0x5e300800, 0xdf3e0c00, disas_simd_scalar_pairwise },
147
147
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
148
new file mode 100644
149
index XXXXXXX..XXXXXXX
150
--- /dev/null
151
+++ b/target/arm/vec_helper.c
152
@@ -XXX,XX +XXX,XX @@
153
+/*
154
+ * ARM AdvSIMD / SVE Vector Operations
155
+ *
156
+ * Copyright (c) 2018 Linaro
157
+ *
158
+ * This library is free software; you can redistribute it and/or
159
+ * modify it under the terms of the GNU Lesser General Public
160
+ * License as published by the Free Software Foundation; either
161
+ * version 2 of the License, or (at your option) any later version.
162
+ *
163
+ * This library is distributed in the hope that it will be useful,
164
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
165
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
166
+ * Lesser General Public License for more details.
167
+ *
168
+ * You should have received a copy of the GNU Lesser General Public
169
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
170
+ */
171
+
172
+#include "qemu/osdep.h"
173
+#include "cpu.h"
174
+#include "exec/exec-all.h"
175
+#include "exec/helper-proto.h"
176
+#include "tcg/tcg-gvec-desc.h"
177
+
178
+
179
+#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
180
+
181
+/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
182
+static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
183
+ int16_t src2, int16_t src3)
184
+{
185
+ /* Simplify:
186
+ * = ((a3 << 16) + ((e1 * e2) << 1) + (1 << 15)) >> 16
187
+ * = ((a3 << 15) + (e1 * e2) + (1 << 14)) >> 15
188
+ */
189
+ int32_t ret = (int32_t)src1 * src2;
190
+ ret = ((int32_t)src3 << 15) + ret + (1 << 14);
191
+ ret >>= 15;
192
+ if (ret != (int16_t)ret) {
193
+ SET_QC();
194
+ ret = (ret < 0 ? -0x8000 : 0x7fff);
195
+ }
196
+ return ret;
197
+}
198
+
199
+uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1,
200
+ uint32_t src2, uint32_t src3)
201
+{
202
+ uint16_t e1 = inl_qrdmlah_s16(env, src1, src2, src3);
203
+ uint16_t e2 = inl_qrdmlah_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
204
+ return deposit32(e1, 16, 16, e2);
205
+}
206
+
207
+/* Signed saturating rounding doubling multiply-subtract high half, 16-bit */
208
+static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
209
+ int16_t src2, int16_t src3)
210
+{
211
+ /* Similarly, using subtraction:
212
+ * = ((a3 << 16) - ((e1 * e2) << 1) + (1 << 15)) >> 16
213
+ * = ((a3 << 15) - (e1 * e2) + (1 << 14)) >> 15
214
+ */
215
+ int32_t ret = (int32_t)src1 * src2;
216
+ ret = ((int32_t)src3 << 15) - ret + (1 << 14);
217
+ ret >>= 15;
218
+ if (ret != (int16_t)ret) {
219
+ SET_QC();
220
+ ret = (ret < 0 ? -0x8000 : 0x7fff);
221
+ }
222
+ return ret;
223
+}
224
+
225
+uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1,
226
+ uint32_t src2, uint32_t src3)
227
+{
228
+ uint16_t e1 = inl_qrdmlsh_s16(env, src1, src2, src3);
229
+ uint16_t e2 = inl_qrdmlsh_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
230
+ return deposit32(e1, 16, 16, e2);
231
+}
232
+
233
+/* Signed saturating rounding doubling multiply-accumulate high half, 32-bit */
234
+uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
235
+ int32_t src2, int32_t src3)
236
+{
237
+ /* Simplify similarly to int_qrdmlah_s16 above. */
238
+ int64_t ret = (int64_t)src1 * src2;
239
+ ret = ((int64_t)src3 << 31) + ret + (1 << 30);
240
+ ret >>= 31;
241
+ if (ret != (int32_t)ret) {
242
+ SET_QC();
243
+ ret = (ret < 0 ? INT32_MIN : INT32_MAX);
244
+ }
245
+ return ret;
246
+}
247
+
248
+/* Signed saturating rounding doubling multiply-subtract high half, 32-bit */
249
+uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
250
+ int32_t src2, int32_t src3)
251
+{
252
+ /* Simplify similarly to int_qrdmlsh_s16 above. */
253
+ int64_t ret = (int64_t)src1 * src2;
254
+ ret = ((int64_t)src3 << 31) - ret + (1 << 30);
255
+ ret >>= 31;
256
+ if (ret != (int32_t)ret) {
257
+ SET_QC();
258
+ ret = (ret < 0 ? INT32_MIN : INT32_MAX);
259
+ }
260
+ return ret;
261
+}
262
--
148
--
263
2.16.2
149
2.20.1
264
150
265
151
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
The integer size check was already outside of the opcode switch;
3
With -Werror=maybe-uninitialized configuration we get
4
move the floating-point size check outside as well. Unify the
4
../hw/i386/intel_iommu.c: In function ‘vtd_context_device_invalidate’:
5
size vs index adjustment between fp and integer paths.
5
../hw/i386/intel_iommu.c:1888:10: error: ‘mask’ may be used
6
uninitialized in this function [-Werror=maybe-uninitialized]
7
1888 | mask = ~mask;
8
| ~~~~~^~~~~~~
6
9
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Add a g_assert_not_reached() to avoid the error.
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
9
Message-id: 20180228193125.20577-4-richard.henderson@linaro.org
12
Signed-off-by: Eric Auger <eric.auger@redhat.com>
13
Reviewed-by: Peter Xu <peterx@redhat.com>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
15
Message-id: 20210309102742.30442-2-eric.auger@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
17
---
12
target/arm/translate-a64.c | 65 +++++++++++++++++++++++-----------------------
18
hw/i386/intel_iommu.c | 2 ++
13
1 file changed, 32 insertions(+), 33 deletions(-)
19
1 file changed, 2 insertions(+)
14
20
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
21
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
16
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
23
--- a/hw/i386/intel_iommu.c
18
+++ b/target/arm/translate-a64.c
24
+++ b/hw/i386/intel_iommu.c
19
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
25
@@ -XXX,XX +XXX,XX @@ static void vtd_context_device_invalidate(IntelIOMMUState *s,
20
case 0x05: /* FMLS */
26
case 3:
21
case 0x09: /* FMUL */
27
mask = 7; /* Mask bit 2:0 in the SID field */
22
case 0x19: /* FMULX */
23
- if (size == 1) {
24
- unallocated_encoding(s);
25
- return;
26
- }
27
is_fp = true;
28
break;
28
break;
29
default:
30
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
31
if (is_fp) {
32
/* convert insn encoded size to TCGMemOp size */
33
switch (size) {
34
- case 2: /* single precision */
35
- size = MO_32;
36
- index = h << 1 | l;
37
- rm |= (m << 4);
38
- break;
39
- case 3: /* double precision */
40
- size = MO_64;
41
- if (l || !is_q) {
42
+ case 0: /* half-precision */
43
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
44
unallocated_encoding(s);
45
return;
46
}
47
- index = h;
48
- rm |= (m << 4);
49
- break;
50
- case 0: /* half precision */
51
size = MO_16;
52
- index = h << 2 | l << 1 | m;
53
- is_fp16 = true;
54
- if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
55
- break;
56
- }
57
- /* fallthru */
58
- default: /* unallocated */
59
- unallocated_encoding(s);
60
- return;
61
- }
62
- } else {
63
- switch (size) {
64
- case 1:
65
- index = h << 2 | l << 1 | m;
66
break;
67
- case 2:
68
- index = h << 1 | l;
69
- rm |= (m << 4);
70
+ case MO_32: /* single precision */
71
+ case MO_64: /* double precision */
72
break;
73
default:
74
unallocated_encoding(s);
75
return;
76
}
77
+ } else {
78
+ switch (size) {
79
+ case MO_8:
80
+ case MO_64:
81
+ unallocated_encoding(s);
82
+ return;
83
+ }
84
+ }
85
+
86
+ /* Given TCGMemOp size, adjust register and indexing. */
87
+ switch (size) {
88
+ case MO_16:
89
+ index = h << 2 | l << 1 | m;
90
+ break;
91
+ case MO_32:
92
+ index = h << 1 | l;
93
+ rm |= m << 4;
94
+ break;
95
+ case MO_64:
96
+ if (l || !is_q) {
97
+ unallocated_encoding(s);
98
+ return;
99
+ }
100
+ index = h;
101
+ rm |= m << 4;
102
+ break;
103
+ default:
29
+ default:
104
+ g_assert_not_reached();
30
+ g_assert_not_reached();
105
}
31
}
106
32
mask = ~mask;
107
if (!fp_access_check(s)) {
33
108
--
34
--
109
2.16.2
35
2.20.1
110
36
111
37
diff view generated by jsdifflib
1
The MPS2 AN505 FPGA image includes a "FPGA control block"
1
From: Eric Auger <eric.auger@redhat.com>
2
which is a small set of registers handling LEDs, buttons
3
and some counters.
4
2
3
Currently get_naturally_aligned_size() is used by the intel iommu
4
to compute the maximum invalidation range based on @size which is
5
a power of 2 while being aligned with the @start address and less
6
than the maximum range defined by @gaw.
7
8
This helper is also useful for other iommu devices (virtio-iommu,
9
SMMUv3) to make sure IOMMU UNMAP notifiers only are called with
10
power of 2 range sizes.
11
12
Let's move this latter into dma-helpers.c and rename it into
13
dma_aligned_pow2_mask(). Also rewrite the helper so that it
14
accomodates UINT64_MAX values for the size mask and max mask.
15
It now returns a mask instead of a size. Change the caller.
16
17
Signed-off-by: Eric Auger <eric.auger@redhat.com>
18
Reviewed-by: Peter Xu <peterx@redhat.com>
19
Message-id: 20210309102742.30442-3-eric.auger@redhat.com
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180220180325.29818-14-peter.maydell@linaro.org
8
---
21
---
9
hw/misc/Makefile.objs | 1 +
22
include/sysemu/dma.h | 12 ++++++++++++
10
include/hw/misc/mps2-fpgaio.h | 43 ++++++++++
23
hw/i386/intel_iommu.c | 30 +++++++-----------------------
11
hw/misc/mps2-fpgaio.c | 176 ++++++++++++++++++++++++++++++++++++++++
24
softmmu/dma-helpers.c | 26 ++++++++++++++++++++++++++
12
default-configs/arm-softmmu.mak | 1 +
25
3 files changed, 45 insertions(+), 23 deletions(-)
13
hw/misc/trace-events | 6 ++
14
5 files changed, 227 insertions(+)
15
create mode 100644 include/hw/misc/mps2-fpgaio.h
16
create mode 100644 hw/misc/mps2-fpgaio.c
17
26
18
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
27
diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
19
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/misc/Makefile.objs
29
--- a/include/sysemu/dma.h
21
+++ b/hw/misc/Makefile.objs
30
+++ b/include/sysemu/dma.h
22
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
31
@@ -XXX,XX +XXX,XX @@ uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg);
23
obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
32
void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
24
obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
33
QEMUSGList *sg, enum BlockAcctType type);
25
obj-$(CONFIG_MIPS_ITU) += mips_itu.o
34
26
+obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
35
+/**
27
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
36
+ * dma_aligned_pow2_mask: Return the address bit mask of the largest
28
37
+ * power of 2 size less or equal than @end - @start + 1, aligned with @start,
29
obj-$(CONFIG_PVPANIC) += pvpanic.o
38
+ * and bounded by 1 << @max_addr_bits bits.
30
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
39
+ *
31
new file mode 100644
40
+ * @start: range start address
32
index XXXXXXX..XXXXXXX
41
+ * @end: range end address (greater than @start)
33
--- /dev/null
42
+ * @max_addr_bits: max address bits (<= 64)
34
+++ b/include/hw/misc/mps2-fpgaio.h
43
+ */
44
+uint64_t dma_aligned_pow2_mask(uint64_t start, uint64_t end,
45
+ int max_addr_bits);
46
+
47
#endif
48
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/i386/intel_iommu.c
51
+++ b/hw/i386/intel_iommu.c
35
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@
36
+/*
53
#include "hw/i386/x86-iommu.h"
37
+ * ARM MPS2 FPGAIO emulation
54
#include "hw/pci-host/q35.h"
38
+ *
55
#include "sysemu/kvm.h"
39
+ * Copyright (c) 2018 Linaro Limited
56
+#include "sysemu/dma.h"
40
+ * Written by Peter Maydell
57
#include "sysemu/sysemu.h"
41
+ *
58
#include "hw/i386/apic_internal.h"
42
+ * This program is free software; you can redistribute it and/or modify
59
#include "kvm/kvm_i386.h"
43
+ * it under the terms of the GNU General Public License version 2 or
60
@@ -XXX,XX +XXX,XX @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
44
+ * (at your option) any later version.
61
return vtd_dev_as;
45
+ */
62
}
63
64
-static uint64_t get_naturally_aligned_size(uint64_t start,
65
- uint64_t size, int gaw)
66
-{
67
- uint64_t max_mask = 1ULL << gaw;
68
- uint64_t alignment = start ? start & -start : max_mask;
69
-
70
- alignment = MIN(alignment, max_mask);
71
- size = MIN(size, max_mask);
72
-
73
- if (alignment <= size) {
74
- /* Increase the alignment of start */
75
- return alignment;
76
- } else {
77
- /* Find the largest page mask from size */
78
- return 1ULL << (63 - clz64(size));
79
- }
80
-}
81
-
82
/* Unmap the whole range in the notifier's scope. */
83
static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
84
{
85
@@ -XXX,XX +XXX,XX @@ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
86
87
while (remain >= VTD_PAGE_SIZE) {
88
IOMMUTLBEvent event;
89
- uint64_t mask = get_naturally_aligned_size(start, remain, s->aw_bits);
90
+ uint64_t mask = dma_aligned_pow2_mask(start, end, s->aw_bits);
91
+ uint64_t size = mask + 1;
92
93
- assert(mask);
94
+ assert(size);
95
96
event.type = IOMMU_NOTIFIER_UNMAP;
97
event.entry.iova = start;
98
- event.entry.addr_mask = mask - 1;
99
+ event.entry.addr_mask = mask;
100
event.entry.target_as = &address_space_memory;
101
event.entry.perm = IOMMU_NONE;
102
/* This field is meaningless for unmap */
103
@@ -XXX,XX +XXX,XX @@ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
104
105
memory_region_notify_iommu_one(n, &event);
106
107
- start += mask;
108
- remain -= mask;
109
+ start += size;
110
+ remain -= size;
111
}
112
113
assert(!remain);
114
diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c
115
index XXXXXXX..XXXXXXX 100644
116
--- a/softmmu/dma-helpers.c
117
+++ b/softmmu/dma-helpers.c
118
@@ -XXX,XX +XXX,XX @@ void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
119
{
120
block_acct_start(blk_get_stats(blk), cookie, sg->size, type);
121
}
46
+
122
+
47
+/* This is a model of the FPGAIO register block in the AN505
123
+uint64_t dma_aligned_pow2_mask(uint64_t start, uint64_t end, int max_addr_bits)
48
+ * FPGA image for the MPS2 dev board; it is documented in the
124
+{
49
+ * application note:
125
+ uint64_t max_mask = UINT64_MAX, addr_mask = end - start;
50
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
126
+ uint64_t alignment_mask, size_mask;
51
+ *
52
+ * QEMU interface:
53
+ * + sysbus MMIO region 0: the register bank
54
+ */
55
+
127
+
56
+#ifndef MPS2_FPGAIO_H
128
+ if (max_addr_bits != 64) {
57
+#define MPS2_FPGAIO_H
129
+ max_mask = (1ULL << max_addr_bits) - 1;
58
+
59
+#include "hw/sysbus.h"
60
+
61
+#define TYPE_MPS2_FPGAIO "mps2-fpgaio"
62
+#define MPS2_FPGAIO(obj) OBJECT_CHECK(MPS2FPGAIO, (obj), TYPE_MPS2_FPGAIO)
63
+
64
+typedef struct {
65
+ /*< private >*/
66
+ SysBusDevice parent_obj;
67
+
68
+ /*< public >*/
69
+ MemoryRegion iomem;
70
+
71
+ uint32_t led0;
72
+ uint32_t prescale;
73
+ uint32_t misc;
74
+
75
+ uint32_t prescale_clk;
76
+} MPS2FPGAIO;
77
+
78
+#endif
79
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
80
new file mode 100644
81
index XXXXXXX..XXXXXXX
82
--- /dev/null
83
+++ b/hw/misc/mps2-fpgaio.c
84
@@ -XXX,XX +XXX,XX @@
85
+/*
86
+ * ARM MPS2 AN505 FPGAIO emulation
87
+ *
88
+ * Copyright (c) 2018 Linaro Limited
89
+ * Written by Peter Maydell
90
+ *
91
+ * This program is free software; you can redistribute it and/or modify
92
+ * it under the terms of the GNU General Public License version 2 or
93
+ * (at your option) any later version.
94
+ */
95
+
96
+/* This is a model of the "FPGA system control and I/O" block found
97
+ * in the AN505 FPGA image for the MPS2 devboard.
98
+ * It is documented in AN505:
99
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
100
+ */
101
+
102
+#include "qemu/osdep.h"
103
+#include "qemu/log.h"
104
+#include "qapi/error.h"
105
+#include "trace.h"
106
+#include "hw/sysbus.h"
107
+#include "hw/registerfields.h"
108
+#include "hw/misc/mps2-fpgaio.h"
109
+
110
+REG32(LED0, 0)
111
+REG32(BUTTON, 8)
112
+REG32(CLK1HZ, 0x10)
113
+REG32(CLK100HZ, 0x14)
114
+REG32(COUNTER, 0x18)
115
+REG32(PRESCALE, 0x1c)
116
+REG32(PSCNTR, 0x20)
117
+REG32(MISC, 0x4c)
118
+
119
+static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
120
+{
121
+ MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
122
+ uint64_t r;
123
+
124
+ switch (offset) {
125
+ case A_LED0:
126
+ r = s->led0;
127
+ break;
128
+ case A_BUTTON:
129
+ /* User-pressable board buttons. We don't model that, so just return
130
+ * zeroes.
131
+ */
132
+ r = 0;
133
+ break;
134
+ case A_PRESCALE:
135
+ r = s->prescale;
136
+ break;
137
+ case A_MISC:
138
+ r = s->misc;
139
+ break;
140
+ case A_CLK1HZ:
141
+ case A_CLK100HZ:
142
+ case A_COUNTER:
143
+ case A_PSCNTR:
144
+ /* These are all upcounters of various frequencies. */
145
+ qemu_log_mask(LOG_UNIMP, "MPS2 FPGAIO: counters unimplemented\n");
146
+ r = 0;
147
+ break;
148
+ default:
149
+ qemu_log_mask(LOG_GUEST_ERROR,
150
+ "MPS2 FPGAIO read: bad offset %x\n", (int) offset);
151
+ r = 0;
152
+ break;
153
+ }
130
+ }
154
+
131
+
155
+ trace_mps2_fpgaio_read(offset, r, size);
132
+ alignment_mask = start ? (start & -start) - 1 : max_mask;
156
+ return r;
133
+ alignment_mask = MIN(alignment_mask, max_mask);
157
+}
134
+ size_mask = MIN(addr_mask, max_mask);
158
+
135
+
159
+static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
136
+ if (alignment_mask <= size_mask) {
160
+ unsigned size)
137
+ /* Increase the alignment of start */
161
+{
138
+ return alignment_mask;
162
+ MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
139
+ } else {
163
+
140
+ /* Find the largest page mask from size */
164
+ trace_mps2_fpgaio_write(offset, value, size);
141
+ if (addr_mask == UINT64_MAX) {
165
+
142
+ return UINT64_MAX;
166
+ switch (offset) {
143
+ }
167
+ case A_LED0:
144
+ return (1ULL << (63 - clz64(addr_mask + 1))) - 1;
168
+ /* LED bits [1:0] control board LEDs. We don't currently have
169
+ * a mechanism for displaying this graphically, so use a trace event.
170
+ */
171
+ trace_mps2_fpgaio_leds(value & 0x02 ? '*' : '.',
172
+ value & 0x01 ? '*' : '.');
173
+ s->led0 = value & 0x3;
174
+ break;
175
+ case A_PRESCALE:
176
+ s->prescale = value;
177
+ break;
178
+ case A_MISC:
179
+ /* These are control bits for some of the other devices on the
180
+ * board (SPI, CLCD, etc). We don't implement that yet, so just
181
+ * make the bits read as written.
182
+ */
183
+ qemu_log_mask(LOG_UNIMP,
184
+ "MPS2 FPGAIO: MISC control bits unimplemented\n");
185
+ s->misc = value;
186
+ break;
187
+ default:
188
+ qemu_log_mask(LOG_GUEST_ERROR,
189
+ "MPS2 FPGAIO write: bad offset 0x%x\n", (int) offset);
190
+ break;
191
+ }
145
+ }
192
+}
146
+}
193
+
147
+
194
+static const MemoryRegionOps mps2_fpgaio_ops = {
195
+ .read = mps2_fpgaio_read,
196
+ .write = mps2_fpgaio_write,
197
+ .endianness = DEVICE_LITTLE_ENDIAN,
198
+};
199
+
200
+static void mps2_fpgaio_reset(DeviceState *dev)
201
+{
202
+ MPS2FPGAIO *s = MPS2_FPGAIO(dev);
203
+
204
+ trace_mps2_fpgaio_reset();
205
+ s->led0 = 0;
206
+ s->prescale = 0;
207
+ s->misc = 0;
208
+}
209
+
210
+static void mps2_fpgaio_init(Object *obj)
211
+{
212
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
213
+ MPS2FPGAIO *s = MPS2_FPGAIO(obj);
214
+
215
+ memory_region_init_io(&s->iomem, obj, &mps2_fpgaio_ops, s,
216
+ "mps2-fpgaio", 0x1000);
217
+ sysbus_init_mmio(sbd, &s->iomem);
218
+}
219
+
220
+static const VMStateDescription mps2_fpgaio_vmstate = {
221
+ .name = "mps2-fpgaio",
222
+ .version_id = 1,
223
+ .minimum_version_id = 1,
224
+ .fields = (VMStateField[]) {
225
+ VMSTATE_UINT32(led0, MPS2FPGAIO),
226
+ VMSTATE_UINT32(prescale, MPS2FPGAIO),
227
+ VMSTATE_UINT32(misc, MPS2FPGAIO),
228
+ VMSTATE_END_OF_LIST()
229
+ }
230
+};
231
+
232
+static Property mps2_fpgaio_properties[] = {
233
+ /* Frequency of the prescale counter */
234
+ DEFINE_PROP_UINT32("prescale-clk", MPS2FPGAIO, prescale_clk, 20000000),
235
+ DEFINE_PROP_END_OF_LIST(),
236
+};
237
+
238
+static void mps2_fpgaio_class_init(ObjectClass *klass, void *data)
239
+{
240
+ DeviceClass *dc = DEVICE_CLASS(klass);
241
+
242
+ dc->vmsd = &mps2_fpgaio_vmstate;
243
+ dc->reset = mps2_fpgaio_reset;
244
+ dc->props = mps2_fpgaio_properties;
245
+}
246
+
247
+static const TypeInfo mps2_fpgaio_info = {
248
+ .name = TYPE_MPS2_FPGAIO,
249
+ .parent = TYPE_SYS_BUS_DEVICE,
250
+ .instance_size = sizeof(MPS2FPGAIO),
251
+ .instance_init = mps2_fpgaio_init,
252
+ .class_init = mps2_fpgaio_class_init,
253
+};
254
+
255
+static void mps2_fpgaio_register_types(void)
256
+{
257
+ type_register_static(&mps2_fpgaio_info);
258
+}
259
+
260
+type_init(mps2_fpgaio_register_types);
261
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
262
index XXXXXXX..XXXXXXX 100644
263
--- a/default-configs/arm-softmmu.mak
264
+++ b/default-configs/arm-softmmu.mak
265
@@ -XXX,XX +XXX,XX @@ CONFIG_STM32F205_SOC=y
266
CONFIG_CMSDK_APB_TIMER=y
267
CONFIG_CMSDK_APB_UART=y
268
269
+CONFIG_MPS2_FPGAIO=y
270
CONFIG_MPS2_SCC=y
271
272
CONFIG_VERSATILE_PCI=y
273
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
274
index XXXXXXX..XXXXXXX 100644
275
--- a/hw/misc/trace-events
276
+++ b/hw/misc/trace-events
277
@@ -XXX,XX +XXX,XX @@ mps2_scc_leds(char led7, char led6, char led5, char led4, char led3, char led2,
278
mps2_scc_cfg_write(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config write: function %d device %d data 0x%" PRIx32
279
mps2_scc_cfg_read(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config read: function %d device %d data 0x%" PRIx32
280
281
+# hw/misc/mps2_fpgaio.c
282
+mps2_fpgaio_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 FPGAIO read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
283
+mps2_fpgaio_write(uint64_t offset, uint64_t data, unsigned size) "MPS2 FPGAIO write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
284
+mps2_fpgaio_reset(void) "MPS2 FPGAIO: reset"
285
+mps2_fpgaio_leds(char led1, char led0) "MPS2 FPGAIO LEDs: %c%c"
286
+
287
# hw/misc/msf2-sysreg.c
288
msf2_sysreg_write(uint64_t offset, uint32_t val, uint32_t prev) "msf2-sysreg write: addr 0x%08" HWADDR_PRIx " data 0x%" PRIx32 " prev 0x%" PRIx32
289
msf2_sysreg_read(uint64_t offset, uint32_t val) "msf2-sysreg read: addr 0x%08" HWADDR_PRIx " data 0x%08" PRIx32
290
--
148
--
291
2.16.2
149
2.20.1
292
150
293
151
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Unmap notifiers work with an address mask assuming an
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
invalidation range of a power of 2. Nothing mandates this
5
Message-id: 20180228193125.20577-12-richard.henderson@linaro.org
5
in the VIRTIO-IOMMU spec.
6
7
So in case the range is not a power of 2, split it into
8
several invalidations.
9
10
Signed-off-by: Eric Auger <eric.auger@redhat.com>
11
Reviewed-by: Peter Xu <peterx@redhat.com>
12
Message-id: 20210309102742.30442-4-eric.auger@redhat.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
14
---
8
target/arm/helper.h | 7 ++++
15
hw/virtio/virtio-iommu.c | 19 ++++++++++++++++---
9
target/arm/translate-a64.c | 48 ++++++++++++++++++++++-
16
1 file changed, 16 insertions(+), 3 deletions(-)
10
target/arm/vec_helper.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++
11
3 files changed, 151 insertions(+), 1 deletion(-)
12
17
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
18
diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
14
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
20
--- a/hw/virtio/virtio-iommu.c
16
+++ b/target/arm/helper.h
21
+++ b/hw/virtio/virtio-iommu.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_qrdmlah_s32, TCG_CALL_NO_RWG,
22
@@ -XXX,XX +XXX,XX @@ static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start,
18
DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s32, TCG_CALL_NO_RWG,
23
hwaddr virt_end)
19
void, ptr, ptr, ptr, ptr, i32)
24
{
20
25
IOMMUTLBEvent event;
21
+DEF_HELPER_FLAGS_5(gvec_fcaddh, TCG_CALL_NO_RWG,
26
+ uint64_t delta = virt_end - virt_start;
22
+ void, ptr, ptr, ptr, ptr, i32)
27
23
+DEF_HELPER_FLAGS_5(gvec_fcadds, TCG_CALL_NO_RWG,
28
if (!(mr->iommu_notify_flags & IOMMU_NOTIFIER_UNMAP)) {
24
+ void, ptr, ptr, ptr, ptr, i32)
29
return;
25
+DEF_HELPER_FLAGS_5(gvec_fcaddd, TCG_CALL_NO_RWG,
30
@@ -XXX,XX +XXX,XX @@ static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start,
26
+ void, ptr, ptr, ptr, ptr, i32)
31
32
event.type = IOMMU_NOTIFIER_UNMAP;
33
event.entry.target_as = &address_space_memory;
34
- event.entry.addr_mask = virt_end - virt_start;
35
- event.entry.iova = virt_start;
36
event.entry.perm = IOMMU_NONE;
37
event.entry.translated_addr = 0;
38
+ event.entry.addr_mask = delta;
39
+ event.entry.iova = virt_start;
40
41
- memory_region_notify_iommu(mr, 0, event);
42
+ if (delta == UINT64_MAX) {
43
+ memory_region_notify_iommu(mr, 0, event);
44
+ }
27
+
45
+
28
#ifdef TARGET_AARCH64
46
+
29
#include "helper-a64.h"
47
+ while (virt_start != virt_end + 1) {
30
#endif
48
+ uint64_t mask = dma_aligned_pow2_mask(virt_start, virt_end, 64);
31
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
49
+
32
index XXXXXXX..XXXXXXX 100644
50
+ event.entry.addr_mask = mask;
33
--- a/target/arm/translate-a64.c
51
+ event.entry.iova = virt_start;
34
+++ b/target/arm/translate-a64.c
52
+ memory_region_notify_iommu(mr, 0, event);
35
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
53
+ virt_start += mask + 1;
36
is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
54
+ }
37
}
55
}
38
56
39
+/* Expand a 3-operand + fpstatus pointer + simd data value operation using
57
static gboolean virtio_iommu_notify_unmap_cb(gpointer key, gpointer value,
40
+ * an out-of-line helper.
41
+ */
42
+static void gen_gvec_op3_fpst(DisasContext *s, bool is_q, int rd, int rn,
43
+ int rm, bool is_fp16, int data,
44
+ gen_helper_gvec_3_ptr *fn)
45
+{
46
+ TCGv_ptr fpst = get_fpstatus_ptr(is_fp16);
47
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
48
+ vec_full_reg_offset(s, rn),
49
+ vec_full_reg_offset(s, rm), fpst,
50
+ is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
51
+ tcg_temp_free_ptr(fpst);
52
+}
53
+
54
/* Set ZF and NF based on a 64 bit result. This is alas fiddlier
55
* than the 32 bit equivalent.
56
*/
57
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
58
int size = extract32(insn, 22, 2);
59
bool u = extract32(insn, 29, 1);
60
bool is_q = extract32(insn, 30, 1);
61
- int feature;
62
+ int feature, rot;
63
64
switch (u * 16 + opcode) {
65
case 0x10: /* SQRDMLAH (vector) */
66
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
67
}
68
feature = ARM_FEATURE_V8_RDM;
69
break;
70
+ case 0xc: /* FCADD, #90 */
71
+ case 0xe: /* FCADD, #270 */
72
+ if (size == 0
73
+ || (size == 1 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))
74
+ || (size == 3 && !is_q)) {
75
+ unallocated_encoding(s);
76
+ return;
77
+ }
78
+ feature = ARM_FEATURE_V8_FCMA;
79
+ break;
80
default:
81
unallocated_encoding(s);
82
return;
83
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
84
}
85
return;
86
87
+ case 0xc: /* FCADD, #90 */
88
+ case 0xe: /* FCADD, #270 */
89
+ rot = extract32(opcode, 1, 1);
90
+ switch (size) {
91
+ case 1:
92
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
93
+ gen_helper_gvec_fcaddh);
94
+ break;
95
+ case 2:
96
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
97
+ gen_helper_gvec_fcadds);
98
+ break;
99
+ case 3:
100
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
101
+ gen_helper_gvec_fcaddd);
102
+ break;
103
+ default:
104
+ g_assert_not_reached();
105
+ }
106
+ return;
107
+
108
default:
109
g_assert_not_reached();
110
}
111
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/target/arm/vec_helper.c
114
+++ b/target/arm/vec_helper.c
115
@@ -XXX,XX +XXX,XX @@
116
#include "exec/exec-all.h"
117
#include "exec/helper-proto.h"
118
#include "tcg/tcg-gvec-desc.h"
119
+#include "fpu/softfloat.h"
120
121
122
+/* Note that vector data is stored in host-endian 64-bit chunks,
123
+ so addressing units smaller than that needs a host-endian fixup. */
124
+#ifdef HOST_WORDS_BIGENDIAN
125
+#define H1(x) ((x) ^ 7)
126
+#define H2(x) ((x) ^ 3)
127
+#define H4(x) ((x) ^ 1)
128
+#else
129
+#define H1(x) (x)
130
+#define H2(x) (x)
131
+#define H4(x) (x)
132
+#endif
133
+
134
#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
135
136
static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
137
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm,
138
}
139
clear_tail(d, opr_sz, simd_maxsz(desc));
140
}
141
+
142
+void HELPER(gvec_fcaddh)(void *vd, void *vn, void *vm,
143
+ void *vfpst, uint32_t desc)
144
+{
145
+ uintptr_t opr_sz = simd_oprsz(desc);
146
+ float16 *d = vd;
147
+ float16 *n = vn;
148
+ float16 *m = vm;
149
+ float_status *fpst = vfpst;
150
+ uint32_t neg_real = extract32(desc, SIMD_DATA_SHIFT, 1);
151
+ uint32_t neg_imag = neg_real ^ 1;
152
+ uintptr_t i;
153
+
154
+ /* Shift boolean to the sign bit so we can xor to negate. */
155
+ neg_real <<= 15;
156
+ neg_imag <<= 15;
157
+
158
+ for (i = 0; i < opr_sz / 2; i += 2) {
159
+ float16 e0 = n[H2(i)];
160
+ float16 e1 = m[H2(i + 1)] ^ neg_imag;
161
+ float16 e2 = n[H2(i + 1)];
162
+ float16 e3 = m[H2(i)] ^ neg_real;
163
+
164
+ d[H2(i)] = float16_add(e0, e1, fpst);
165
+ d[H2(i + 1)] = float16_add(e2, e3, fpst);
166
+ }
167
+ clear_tail(d, opr_sz, simd_maxsz(desc));
168
+}
169
+
170
+void HELPER(gvec_fcadds)(void *vd, void *vn, void *vm,
171
+ void *vfpst, uint32_t desc)
172
+{
173
+ uintptr_t opr_sz = simd_oprsz(desc);
174
+ float32 *d = vd;
175
+ float32 *n = vn;
176
+ float32 *m = vm;
177
+ float_status *fpst = vfpst;
178
+ uint32_t neg_real = extract32(desc, SIMD_DATA_SHIFT, 1);
179
+ uint32_t neg_imag = neg_real ^ 1;
180
+ uintptr_t i;
181
+
182
+ /* Shift boolean to the sign bit so we can xor to negate. */
183
+ neg_real <<= 31;
184
+ neg_imag <<= 31;
185
+
186
+ for (i = 0; i < opr_sz / 4; i += 2) {
187
+ float32 e0 = n[H4(i)];
188
+ float32 e1 = m[H4(i + 1)] ^ neg_imag;
189
+ float32 e2 = n[H4(i + 1)];
190
+ float32 e3 = m[H4(i)] ^ neg_real;
191
+
192
+ d[H4(i)] = float32_add(e0, e1, fpst);
193
+ d[H4(i + 1)] = float32_add(e2, e3, fpst);
194
+ }
195
+ clear_tail(d, opr_sz, simd_maxsz(desc));
196
+}
197
+
198
+void HELPER(gvec_fcaddd)(void *vd, void *vn, void *vm,
199
+ void *vfpst, uint32_t desc)
200
+{
201
+ uintptr_t opr_sz = simd_oprsz(desc);
202
+ float64 *d = vd;
203
+ float64 *n = vn;
204
+ float64 *m = vm;
205
+ float_status *fpst = vfpst;
206
+ uint64_t neg_real = extract64(desc, SIMD_DATA_SHIFT, 1);
207
+ uint64_t neg_imag = neg_real ^ 1;
208
+ uintptr_t i;
209
+
210
+ /* Shift boolean to the sign bit so we can xor to negate. */
211
+ neg_real <<= 63;
212
+ neg_imag <<= 63;
213
+
214
+ for (i = 0; i < opr_sz / 8; i += 2) {
215
+ float64 e0 = n[i];
216
+ float64 e1 = m[i + 1] ^ neg_imag;
217
+ float64 e2 = n[i + 1];
218
+ float64 e3 = m[i] ^ neg_real;
219
+
220
+ d[i] = float64_add(e0, e1, fpst);
221
+ d[i + 1] = float64_add(e2, e3, fpst);
222
+ }
223
+ clear_tail(d, opr_sz, simd_maxsz(desc));
224
+}
225
--
58
--
226
2.16.2
59
2.20.1
227
60
228
61
diff view generated by jsdifflib
1
Add remaining easy registers to iotkit-secctl:
1
From: Eric Auger <eric.auger@redhat.com>
2
* NSCCFG just routes its two bits out to external GPIO lines
3
* BRGINSTAT/BRGINTCLR/BRGINTEN can be dummies, because QEMU's
4
bus fabric can never report errors
5
2
3
If the asid is not set, do not attempt to locate the key directly
4
as all inserted keys have a valid asid.
5
6
Use g_hash_table_foreach_remove instead.
7
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
9
Message-id: 20210309102742.30442-5-eric.auger@redhat.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20180220180325.29818-18-peter.maydell@linaro.org
8
---
12
---
9
include/hw/misc/iotkit-secctl.h | 4 ++++
13
hw/arm/smmu-common.c | 2 +-
10
hw/misc/iotkit-secctl.c | 32 ++++++++++++++++++++++++++------
14
1 file changed, 1 insertion(+), 1 deletion(-)
11
2 files changed, 30 insertions(+), 6 deletions(-)
12
15
13
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
16
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/misc/iotkit-secctl.h
18
--- a/hw/arm/smmu-common.c
16
+++ b/include/hw/misc/iotkit-secctl.h
19
+++ b/hw/arm/smmu-common.c
17
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ inline void
18
* + sysbus MMIO region 1 is the "non-secure privilege control block" registers
21
smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
19
* + named GPIO output "sec_resp_cfg" indicating whether blocked accesses
22
uint8_t tg, uint64_t num_pages, uint8_t ttl)
20
* should RAZ/WI or bus error
23
{
21
+ * + named GPIO output "nsc_cfg" whose value tracks the NSCCFG register value
24
- if (ttl && (num_pages == 1)) {
22
* Controlling the 2 APB PPCs in the IoTKit:
25
+ if (ttl && (num_pages == 1) && (asid >= 0)) {
23
* + named GPIO outputs apb_ppc0_nonsec[0..2] and apb_ppc1_nonsec
26
SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova, tg, ttl);
24
* + named GPIO outputs apb_ppc0_ap[0..2] and apb_ppc1_ap
27
25
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
28
g_hash_table_remove(s->iotlb, &key);
26
27
/*< public >*/
28
qemu_irq sec_resp_cfg;
29
+ qemu_irq nsc_cfg_irq;
30
31
MemoryRegion s_regs;
32
MemoryRegion ns_regs;
33
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
34
uint32_t secppcintstat;
35
uint32_t secppcinten;
36
uint32_t secrespcfg;
37
+ uint32_t nsccfg;
38
+ uint32_t brginten;
39
40
IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
41
IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
42
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/misc/iotkit-secctl.c
45
+++ b/hw/misc/iotkit-secctl.c
46
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
47
case A_SECRESPCFG:
48
r = s->secrespcfg;
49
break;
50
+ case A_NSCCFG:
51
+ r = s->nsccfg;
52
+ break;
53
case A_SECPPCINTSTAT:
54
r = s->secppcintstat;
55
break;
56
case A_SECPPCINTEN:
57
r = s->secppcinten;
58
break;
59
+ case A_BRGINTSTAT:
60
+ /* QEMU's bus fabric can never report errors as it doesn't buffer
61
+ * writes, so we never report bridge interrupts.
62
+ */
63
+ r = 0;
64
+ break;
65
+ case A_BRGINTEN:
66
+ r = s->brginten;
67
+ break;
68
case A_AHBNSPPCEXP0:
69
case A_AHBNSPPCEXP1:
70
case A_AHBNSPPCEXP2:
71
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
72
case A_APBSPPPCEXP3:
73
r = s->apbexp[offset_to_ppc_idx(offset)].sp;
74
break;
75
- case A_NSCCFG:
76
case A_SECMPCINTSTATUS:
77
case A_SECMSCINTSTAT:
78
case A_SECMSCINTEN:
79
- case A_BRGINTSTAT:
80
- case A_BRGINTEN:
81
case A_NSMSCEXP:
82
qemu_log_mask(LOG_UNIMP,
83
"IoTKit SecCtl S block read: "
84
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
85
}
86
87
switch (offset) {
88
+ case A_NSCCFG:
89
+ s->nsccfg = value & 3;
90
+ qemu_set_irq(s->nsc_cfg_irq, s->nsccfg);
91
+ break;
92
case A_SECRESPCFG:
93
value &= 1;
94
s->secrespcfg = value;
95
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
96
s->secppcinten = value & 0x00f000f3;
97
foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
98
break;
99
+ case A_BRGINTCLR:
100
+ break;
101
+ case A_BRGINTEN:
102
+ s->brginten = value & 0xffff0000;
103
+ break;
104
case A_AHBNSPPCEXP0:
105
case A_AHBNSPPCEXP1:
106
case A_AHBNSPPCEXP2:
107
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
108
ppc = &s->apbexp[offset_to_ppc_idx(offset)];
109
iotkit_secctl_ppc_sp_write(ppc, value);
110
break;
111
- case A_NSCCFG:
112
case A_SECMSCINTCLR:
113
case A_SECMSCINTEN:
114
- case A_BRGINTCLR:
115
- case A_BRGINTEN:
116
qemu_log_mask(LOG_UNIMP,
117
"IoTKit SecCtl S block write: "
118
"unimplemented offset 0x%x\n", offset);
119
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_reset(DeviceState *dev)
120
s->secppcintstat = 0;
121
s->secppcinten = 0;
122
s->secrespcfg = 0;
123
+ s->nsccfg = 0;
124
+ s->brginten = 0;
125
126
foreach_ppc(s, iotkit_secctl_reset_ppc);
127
}
128
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
129
}
130
131
qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
132
+ qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
133
134
memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
135
s, "iotkit-secctl-s-regs", 0x1000);
136
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_secctl_vmstate = {
137
VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
138
VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
139
VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
140
+ VMSTATE_UINT32(nsccfg, IoTKitSecCtl),
141
+ VMSTATE_UINT32(brginten, IoTKitSecCtl),
142
VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
143
iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
144
VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
145
--
29
--
146
2.16.2
30
2.20.1
147
31
148
32
diff view generated by jsdifflib
1
Add a function load_ramdisk_as() which behaves like the existing
1
From: Eric Auger <eric.auger@redhat.com>
2
load_ramdisk() but allows the caller to specify the AddressSpace
3
to use. This matches the pattern we have already for various
4
other loader functions.
5
2
3
As of today, the driver can invalidate a number of pages that is
4
not a power of 2. However IOTLB unmap notifications and internal
5
IOTLB invalidations work with masks leading to erroneous
6
invalidations.
7
8
In case the range is not a power of 2, split invalidations into
9
power of 2 invalidations.
10
11
When looking for a single page entry in the vSMMU internal IOTLB,
12
let's make sure that if the entry is not found using a
13
g_hash_table_remove() we iterate over all the entries to find a
14
potential range that overlaps it.
15
16
Signed-off-by: Eric Auger <eric.auger@redhat.com>
17
Message-id: 20210309102742.30442-6-eric.auger@redhat.com
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180220180325.29818-2-peter.maydell@linaro.org
10
---
20
---
11
include/hw/loader.h | 12 +++++++++++-
21
hw/arm/smmu-common.c | 30 ++++++++++++++++++------------
12
hw/core/loader.c | 8 +++++++-
22
hw/arm/smmuv3.c | 24 ++++++++++++++++++++----
13
2 files changed, 18 insertions(+), 2 deletions(-)
23
2 files changed, 38 insertions(+), 16 deletions(-)
14
24
15
diff --git a/include/hw/loader.h b/include/hw/loader.h
25
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
16
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/loader.h
27
--- a/hw/arm/smmu-common.c
18
+++ b/include/hw/loader.h
28
+++ b/hw/arm/smmu-common.c
19
@@ -XXX,XX +XXX,XX @@ int load_uimage(const char *filename, hwaddr *ep,
29
@@ -XXX,XX +XXX,XX @@ inline void
20
void *translate_opaque);
30
smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
21
31
uint8_t tg, uint64_t num_pages, uint8_t ttl)
22
/**
32
{
23
- * load_ramdisk:
33
+ /* if tg is not set we use 4KB range invalidation */
24
+ * load_ramdisk_as:
34
+ uint8_t granule = tg ? tg * 2 + 10 : 12;
25
* @filename: Path to the ramdisk image
26
* @addr: Memory address to load the ramdisk to
27
* @max_sz: Maximum allowed ramdisk size (for non-u-boot ramdisks)
28
+ * @as: The AddressSpace to load the ELF to. The value of address_space_memory
29
+ * is used if nothing is supplied here.
30
*
31
* Load a ramdisk image with U-Boot header to the specified memory
32
* address.
33
*
34
* Returns the size of the loaded image on success, -1 otherwise.
35
*/
36
+int load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
37
+ AddressSpace *as);
38
+
35
+
39
+/**
36
if (ttl && (num_pages == 1) && (asid >= 0)) {
40
+ * load_ramdisk:
37
SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova, tg, ttl);
41
+ * Same as load_ramdisk_as(), but doesn't allow the caller to specify
38
42
+ * an AddressSpace.
39
- g_hash_table_remove(s->iotlb, &key);
43
+ */
40
- } else {
44
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz);
41
- /* if tg is not set we use 4KB range invalidation */
45
42
- uint8_t granule = tg ? tg * 2 + 10 : 12;
46
ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, size_t srclen);
43
-
47
diff --git a/hw/core/loader.c b/hw/core/loader.c
44
- SMMUIOTLBPageInvInfo info = {
45
- .asid = asid, .iova = iova,
46
- .mask = (num_pages * 1 << granule) - 1};
47
-
48
- g_hash_table_foreach_remove(s->iotlb,
49
- smmu_hash_remove_by_asid_iova,
50
- &info);
51
+ if (g_hash_table_remove(s->iotlb, &key)) {
52
+ return;
53
+ }
54
+ /*
55
+ * if the entry is not found, let's see if it does not
56
+ * belong to a larger IOTLB entry
57
+ */
58
}
59
+
60
+ SMMUIOTLBPageInvInfo info = {
61
+ .asid = asid, .iova = iova,
62
+ .mask = (num_pages * 1 << granule) - 1};
63
+
64
+ g_hash_table_foreach_remove(s->iotlb,
65
+ smmu_hash_remove_by_asid_iova,
66
+ &info);
67
}
68
69
inline void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid)
70
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
48
index XXXXXXX..XXXXXXX 100644
71
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/core/loader.c
72
--- a/hw/arm/smmuv3.c
50
+++ b/hw/core/loader.c
73
+++ b/hw/arm/smmuv3.c
51
@@ -XXX,XX +XXX,XX @@ int load_uimage_as(const char *filename, hwaddr *ep, hwaddr *loadaddr,
74
@@ -XXX,XX +XXX,XX @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
52
75
uint16_t vmid = CMD_VMID(cmd);
53
/* Load a ramdisk. */
76
bool leaf = CMD_LEAF(cmd);
54
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz)
77
uint8_t tg = CMD_TG(cmd);
55
+{
78
- hwaddr num_pages = 1;
56
+ return load_ramdisk_as(filename, addr, max_sz, NULL);
79
+ uint64_t first_page = 0, last_page;
57
+}
80
+ uint64_t num_pages = 1;
81
int asid = -1;
82
83
if (tg) {
84
@@ -XXX,XX +XXX,XX @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
85
if (type == SMMU_CMD_TLBI_NH_VA) {
86
asid = CMD_ASID(cmd);
87
}
88
- trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, num_pages, ttl, leaf);
89
- smmuv3_inv_notifiers_iova(s, asid, addr, tg, num_pages);
90
- smmu_iotlb_inv_iova(s, asid, addr, tg, num_pages, ttl);
58
+
91
+
59
+int load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
92
+ /* Split invalidations into ^2 range invalidations */
60
+ AddressSpace *as)
93
+ last_page = num_pages - 1;
61
{
94
+ while (num_pages) {
62
return load_uboot_image(filename, NULL, &addr, NULL, IH_TYPE_RAMDISK,
95
+ uint8_t granule = tg * 2 + 10;
63
- NULL, NULL, NULL);
96
+ uint64_t mask, count;
64
+ NULL, NULL, as);
97
+
98
+ mask = dma_aligned_pow2_mask(first_page, last_page, 64 - granule);
99
+ count = mask + 1;
100
+
101
+ trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, count, ttl, leaf);
102
+ smmuv3_inv_notifiers_iova(s, asid, addr, tg, count);
103
+ smmu_iotlb_inv_iova(s, asid, addr, tg, count, ttl);
104
+
105
+ num_pages -= count;
106
+ first_page += count;
107
+ addr += count * BIT_ULL(granule);
108
+ }
65
}
109
}
66
110
67
/* Load a gzip-compressed kernel to a dynamically allocated buffer. */
111
static int smmuv3_cmdq_consume(SMMUv3State *s)
68
--
112
--
69
2.16.2
113
2.20.1
70
114
71
115
diff view generated by jsdifflib
1
Add a model of the TrustZone peripheral protection controller (PPC),
1
From: Eric Auger <eric.auger@redhat.com>
2
which is used to gate transactions to non-TZ-aware peripherals so
3
that secure software can configure them to not be accessible to
4
non-secure software.
5
2
3
If the whole SID range (32b) is invalidated (SMMU_CMD_CFGI_ALL),
4
@end overflows and we fail to handle the command properly.
5
6
Once this gets fixed, the current code really is awkward in the
7
sense it loops over the whole range instead of removing the
8
currently cached configs through a hash table lookup.
9
10
Fix both the overflow and the lookup.
11
12
Signed-off-by: Eric Auger <eric.auger@redhat.com>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20210309102742.30442-7-eric.auger@redhat.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-15-peter.maydell@linaro.org
9
---
16
---
10
hw/misc/Makefile.objs | 2 +
17
hw/arm/smmu-internal.h | 5 +++++
11
include/hw/misc/tz-ppc.h | 101 ++++++++++++++
18
hw/arm/smmuv3.c | 34 ++++++++++++++++++++--------------
12
hw/misc/tz-ppc.c | 302 ++++++++++++++++++++++++++++++++++++++++
19
2 files changed, 25 insertions(+), 14 deletions(-)
13
default-configs/arm-softmmu.mak | 2 +
14
hw/misc/trace-events | 11 ++
15
5 files changed, 418 insertions(+)
16
create mode 100644 include/hw/misc/tz-ppc.h
17
create mode 100644 hw/misc/tz-ppc.c
18
20
19
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
21
diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h
20
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/misc/Makefile.objs
23
--- a/hw/arm/smmu-internal.h
22
+++ b/hw/misc/Makefile.objs
24
+++ b/hw/arm/smmu-internal.h
23
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MIPS_ITU) += mips_itu.o
25
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUIOTLBPageInvInfo {
24
obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
26
uint64_t mask;
25
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
27
} SMMUIOTLBPageInvInfo;
26
28
27
+obj-$(CONFIG_TZ_PPC) += tz-ppc.o
29
+typedef struct SMMUSIDRange {
30
+ uint32_t start;
31
+ uint32_t end;
32
+} SMMUSIDRange;
28
+
33
+
29
obj-$(CONFIG_PVPANIC) += pvpanic.o
34
#endif
30
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
35
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
31
obj-$(CONFIG_AUX) += auxbus.o
36
index XXXXXXX..XXXXXXX 100644
32
diff --git a/include/hw/misc/tz-ppc.h b/include/hw/misc/tz-ppc.h
37
--- a/hw/arm/smmuv3.c
33
new file mode 100644
38
+++ b/hw/arm/smmuv3.c
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/include/hw/misc/tz-ppc.h
37
@@ -XXX,XX +XXX,XX @@
39
@@ -XXX,XX +XXX,XX @@
38
+/*
40
39
+ * ARM TrustZone peripheral protection controller emulation
41
#include "hw/arm/smmuv3.h"
40
+ *
42
#include "smmuv3-internal.h"
41
+ * Copyright (c) 2018 Linaro Limited
43
+#include "smmu-internal.h"
42
+ * Written by Peter Maydell
44
43
+ *
45
/**
44
+ * This program is free software; you can redistribute it and/or modify
46
* smmuv3_trigger_irq - pulse @irq if enabled and update
45
+ * it under the terms of the GNU General Public License version 2 or
47
@@ -XXX,XX +XXX,XX @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
46
+ * (at your option) any later version.
48
}
47
+ */
49
}
50
51
+static gboolean
52
+smmuv3_invalidate_ste(gpointer key, gpointer value, gpointer user_data)
53
+{
54
+ SMMUDevice *sdev = (SMMUDevice *)key;
55
+ uint32_t sid = smmu_get_sid(sdev);
56
+ SMMUSIDRange *sid_range = (SMMUSIDRange *)user_data;
48
+
57
+
49
+/* This is a model of the TrustZone peripheral protection controller (PPC).
58
+ if (sid < sid_range->start || sid > sid_range->end) {
50
+ * It is documented in the ARM CoreLink SIE-200 System IP for Embedded TRM
51
+ * (DDI 0571G):
52
+ * https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g
53
+ *
54
+ * The PPC sits in front of peripherals and allows secure software to
55
+ * configure it to either pass through or reject transactions.
56
+ * Rejected transactions may be configured to either be aborted, or to
57
+ * behave as RAZ/WI. An interrupt can be signalled for a rejected transaction.
58
+ *
59
+ * The PPC has no register interface -- it is configured purely by a
60
+ * collection of input signals from other hardware in the system. Typically
61
+ * they are either hardwired or exposed in an ad-hoc register interface by
62
+ * the SoC that uses the PPC.
63
+ *
64
+ * This QEMU model can be used to model either the AHB5 or APB4 TZ PPC,
65
+ * since the only difference between them is that the AHB version has a
66
+ * "default" port which has no security checks applied. In QEMU the default
67
+ * port can be emulated simply by wiring its downstream devices directly
68
+ * into the parent address space, since the PPC does not need to intercept
69
+ * transactions there.
70
+ *
71
+ * In the hardware, selection of which downstream port to use is done by
72
+ * the user's decode logic asserting one of the hsel[] signals. In QEMU,
73
+ * we provide 16 MMIO regions, one per port, and the user maps these into
74
+ * the desired addresses to implement the address decode.
75
+ *
76
+ * QEMU interface:
77
+ * + sysbus MMIO regions 0..15: MemoryRegions defining the upstream end
78
+ * of each of the 16 ports of the PPC
79
+ * + Property "port[0..15]": MemoryRegion defining the downstream device(s)
80
+ * for each of the 16 ports of the PPC
81
+ * + Named GPIO inputs "cfg_nonsec[0..15]": set to 1 if the port should be
82
+ * accessible to NonSecure transactions
83
+ * + Named GPIO inputs "cfg_ap[0..15]": set to 1 if the port should be
84
+ * accessible to non-privileged transactions
85
+ * + Named GPIO input "cfg_sec_resp": set to 1 if a rejected transaction should
86
+ * result in a transaction error, or 0 for the transaction to RAZ/WI
87
+ * + Named GPIO input "irq_enable": set to 1 to enable interrupts
88
+ * + Named GPIO input "irq_clear": set to 1 to clear a pending interrupt
89
+ * + Named GPIO output "irq": set for a transaction-failed interrupt
90
+ * + Property "NONSEC_MASK": if a bit is set in this mask then accesses to
91
+ * the associated port do not have the TZ security check performed. (This
92
+ * corresponds to the hardware allowing this to be set as a Verilog
93
+ * parameter.)
94
+ */
95
+
96
+#ifndef TZ_PPC_H
97
+#define TZ_PPC_H
98
+
99
+#include "hw/sysbus.h"
100
+
101
+#define TYPE_TZ_PPC "tz-ppc"
102
+#define TZ_PPC(obj) OBJECT_CHECK(TZPPC, (obj), TYPE_TZ_PPC)
103
+
104
+#define TZ_NUM_PORTS 16
105
+
106
+typedef struct TZPPC TZPPC;
107
+
108
+typedef struct TZPPCPort {
109
+ TZPPC *ppc;
110
+ MemoryRegion upstream;
111
+ AddressSpace downstream_as;
112
+ MemoryRegion *downstream;
113
+} TZPPCPort;
114
+
115
+struct TZPPC {
116
+ /*< private >*/
117
+ SysBusDevice parent_obj;
118
+
119
+ /*< public >*/
120
+
121
+ /* State: these just track the values of our input signals */
122
+ bool cfg_nonsec[TZ_NUM_PORTS];
123
+ bool cfg_ap[TZ_NUM_PORTS];
124
+ bool cfg_sec_resp;
125
+ bool irq_enable;
126
+ bool irq_clear;
127
+ /* State: are we asserting irq ? */
128
+ bool irq_status;
129
+
130
+ qemu_irq irq;
131
+
132
+ /* Properties */
133
+ uint32_t nonsec_mask;
134
+
135
+ TZPPCPort port[TZ_NUM_PORTS];
136
+};
137
+
138
+#endif
139
diff --git a/hw/misc/tz-ppc.c b/hw/misc/tz-ppc.c
140
new file mode 100644
141
index XXXXXXX..XXXXXXX
142
--- /dev/null
143
+++ b/hw/misc/tz-ppc.c
144
@@ -XXX,XX +XXX,XX @@
145
+/*
146
+ * ARM TrustZone peripheral protection controller emulation
147
+ *
148
+ * Copyright (c) 2018 Linaro Limited
149
+ * Written by Peter Maydell
150
+ *
151
+ * This program is free software; you can redistribute it and/or modify
152
+ * it under the terms of the GNU General Public License version 2 or
153
+ * (at your option) any later version.
154
+ */
155
+
156
+#include "qemu/osdep.h"
157
+#include "qemu/log.h"
158
+#include "qapi/error.h"
159
+#include "trace.h"
160
+#include "hw/sysbus.h"
161
+#include "hw/registerfields.h"
162
+#include "hw/misc/tz-ppc.h"
163
+
164
+static void tz_ppc_update_irq(TZPPC *s)
165
+{
166
+ bool level = s->irq_status && s->irq_enable;
167
+
168
+ trace_tz_ppc_update_irq(level);
169
+ qemu_set_irq(s->irq, level);
170
+}
171
+
172
+static void tz_ppc_cfg_nonsec(void *opaque, int n, int level)
173
+{
174
+ TZPPC *s = TZ_PPC(opaque);
175
+
176
+ assert(n < TZ_NUM_PORTS);
177
+ trace_tz_ppc_cfg_nonsec(n, level);
178
+ s->cfg_nonsec[n] = level;
179
+}
180
+
181
+static void tz_ppc_cfg_ap(void *opaque, int n, int level)
182
+{
183
+ TZPPC *s = TZ_PPC(opaque);
184
+
185
+ assert(n < TZ_NUM_PORTS);
186
+ trace_tz_ppc_cfg_ap(n, level);
187
+ s->cfg_ap[n] = level;
188
+}
189
+
190
+static void tz_ppc_cfg_sec_resp(void *opaque, int n, int level)
191
+{
192
+ TZPPC *s = TZ_PPC(opaque);
193
+
194
+ trace_tz_ppc_cfg_sec_resp(level);
195
+ s->cfg_sec_resp = level;
196
+}
197
+
198
+static void tz_ppc_irq_enable(void *opaque, int n, int level)
199
+{
200
+ TZPPC *s = TZ_PPC(opaque);
201
+
202
+ trace_tz_ppc_irq_enable(level);
203
+ s->irq_enable = level;
204
+ tz_ppc_update_irq(s);
205
+}
206
+
207
+static void tz_ppc_irq_clear(void *opaque, int n, int level)
208
+{
209
+ TZPPC *s = TZ_PPC(opaque);
210
+
211
+ trace_tz_ppc_irq_clear(level);
212
+
213
+ s->irq_clear = level;
214
+ if (level) {
215
+ s->irq_status = false;
216
+ tz_ppc_update_irq(s);
217
+ }
218
+}
219
+
220
+static bool tz_ppc_check(TZPPC *s, int n, MemTxAttrs attrs)
221
+{
222
+ /* Check whether to allow an access to port n; return true if
223
+ * the check passes, and false if the transaction must be blocked.
224
+ * If the latter, the caller must check cfg_sec_resp to determine
225
+ * whether to abort or RAZ/WI the transaction.
226
+ * The checks are:
227
+ * + nonsec_mask suppresses any check of the secure attribute
228
+ * + otherwise, block if cfg_nonsec is 1 and transaction is secure,
229
+ * or if cfg_nonsec is 0 and transaction is non-secure
230
+ * + block if transaction is usermode and cfg_ap is 0
231
+ */
232
+ if ((attrs.secure == s->cfg_nonsec[n] && !(s->nonsec_mask & (1 << n))) ||
233
+ (attrs.user && !s->cfg_ap[n])) {
234
+ /* Block the transaction. */
235
+ if (!s->irq_clear) {
236
+ /* Note that holding irq_clear high suppresses interrupts */
237
+ s->irq_status = true;
238
+ tz_ppc_update_irq(s);
239
+ }
240
+ return false;
59
+ return false;
241
+ }
60
+ }
61
+ trace_smmuv3_config_cache_inv(sid);
242
+ return true;
62
+ return true;
243
+}
63
+}
244
+
64
+
245
+static MemTxResult tz_ppc_read(void *opaque, hwaddr addr, uint64_t *pdata,
65
static int smmuv3_cmdq_consume(SMMUv3State *s)
246
+ unsigned size, MemTxAttrs attrs)
66
{
247
+{
67
SMMUState *bs = ARM_SMMU(s);
248
+ TZPPCPort *p = opaque;
68
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
249
+ TZPPC *s = p->ppc;
69
}
250
+ int n = p - s->port;
70
case SMMU_CMD_CFGI_STE_RANGE: /* same as SMMU_CMD_CFGI_ALL */
251
+ AddressSpace *as = &p->downstream_as;
71
{
252
+ uint64_t data;
72
- uint32_t start = CMD_SID(&cmd), end, i;
253
+ MemTxResult res;
73
+ uint32_t start = CMD_SID(&cmd);
254
+
74
uint8_t range = CMD_STE_RANGE(&cmd);
255
+ if (!tz_ppc_check(s, n, attrs)) {
75
+ uint64_t end = start + (1ULL << (range + 1)) - 1;
256
+ trace_tz_ppc_read_blocked(n, addr, attrs.secure, attrs.user);
76
+ SMMUSIDRange sid_range = {start, end};
257
+ if (s->cfg_sec_resp) {
77
258
+ return MEMTX_ERROR;
78
if (CMD_SSEC(&cmd)) {
259
+ } else {
79
cmd_error = SMMU_CERROR_ILL;
260
+ *pdata = 0;
80
break;
261
+ return MEMTX_OK;
81
}
262
+ }
82
-
263
+ }
83
- end = start + (1 << (range + 1)) - 1;
264
+
84
trace_smmuv3_cmdq_cfgi_ste_range(start, end);
265
+ switch (size) {
85
-
266
+ case 1:
86
- for (i = start; i <= end; i++) {
267
+ data = address_space_ldub(as, addr, attrs, &res);
87
- IOMMUMemoryRegion *mr = smmu_iommu_mr(bs, i);
268
+ break;
88
- SMMUDevice *sdev;
269
+ case 2:
89
-
270
+ data = address_space_lduw_le(as, addr, attrs, &res);
90
- if (!mr) {
271
+ break;
91
- continue;
272
+ case 4:
92
- }
273
+ data = address_space_ldl_le(as, addr, attrs, &res);
93
- sdev = container_of(mr, SMMUDevice, iommu);
274
+ break;
94
- smmuv3_flush_config(sdev);
275
+ case 8:
95
- }
276
+ data = address_space_ldq_le(as, addr, attrs, &res);
96
+ g_hash_table_foreach_remove(bs->configs, smmuv3_invalidate_ste,
277
+ break;
97
+ &sid_range);
278
+ default:
98
break;
279
+ g_assert_not_reached();
99
}
280
+ }
100
case SMMU_CMD_CFGI_CD:
281
+ *pdata = data;
282
+ return res;
283
+}
284
+
285
+static MemTxResult tz_ppc_write(void *opaque, hwaddr addr, uint64_t val,
286
+ unsigned size, MemTxAttrs attrs)
287
+{
288
+ TZPPCPort *p = opaque;
289
+ TZPPC *s = p->ppc;
290
+ AddressSpace *as = &p->downstream_as;
291
+ int n = p - s->port;
292
+ MemTxResult res;
293
+
294
+ if (!tz_ppc_check(s, n, attrs)) {
295
+ trace_tz_ppc_write_blocked(n, addr, attrs.secure, attrs.user);
296
+ if (s->cfg_sec_resp) {
297
+ return MEMTX_ERROR;
298
+ } else {
299
+ return MEMTX_OK;
300
+ }
301
+ }
302
+
303
+ switch (size) {
304
+ case 1:
305
+ address_space_stb(as, addr, val, attrs, &res);
306
+ break;
307
+ case 2:
308
+ address_space_stw_le(as, addr, val, attrs, &res);
309
+ break;
310
+ case 4:
311
+ address_space_stl_le(as, addr, val, attrs, &res);
312
+ break;
313
+ case 8:
314
+ address_space_stq_le(as, addr, val, attrs, &res);
315
+ break;
316
+ default:
317
+ g_assert_not_reached();
318
+ }
319
+ return res;
320
+}
321
+
322
+static const MemoryRegionOps tz_ppc_ops = {
323
+ .read_with_attrs = tz_ppc_read,
324
+ .write_with_attrs = tz_ppc_write,
325
+ .endianness = DEVICE_LITTLE_ENDIAN,
326
+};
327
+
328
+static void tz_ppc_reset(DeviceState *dev)
329
+{
330
+ TZPPC *s = TZ_PPC(dev);
331
+
332
+ trace_tz_ppc_reset();
333
+ s->cfg_sec_resp = false;
334
+ memset(s->cfg_nonsec, 0, sizeof(s->cfg_nonsec));
335
+ memset(s->cfg_ap, 0, sizeof(s->cfg_ap));
336
+}
337
+
338
+static void tz_ppc_init(Object *obj)
339
+{
340
+ DeviceState *dev = DEVICE(obj);
341
+ TZPPC *s = TZ_PPC(obj);
342
+
343
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_nonsec, "cfg_nonsec", TZ_NUM_PORTS);
344
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_ap, "cfg_ap", TZ_NUM_PORTS);
345
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_sec_resp, "cfg_sec_resp", 1);
346
+ qdev_init_gpio_in_named(dev, tz_ppc_irq_enable, "irq_enable", 1);
347
+ qdev_init_gpio_in_named(dev, tz_ppc_irq_clear, "irq_clear", 1);
348
+ qdev_init_gpio_out_named(dev, &s->irq, "irq", 1);
349
+}
350
+
351
+static void tz_ppc_realize(DeviceState *dev, Error **errp)
352
+{
353
+ Object *obj = OBJECT(dev);
354
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
355
+ TZPPC *s = TZ_PPC(dev);
356
+ int i;
357
+
358
+ /* We can't create the upstream end of the port until realize,
359
+ * as we don't know the size of the MR used as the downstream until then.
360
+ */
361
+ for (i = 0; i < TZ_NUM_PORTS; i++) {
362
+ TZPPCPort *port = &s->port[i];
363
+ char *name;
364
+ uint64_t size;
365
+
366
+ if (!port->downstream) {
367
+ continue;
368
+ }
369
+
370
+ name = g_strdup_printf("tz-ppc-port[%d]", i);
371
+
372
+ port->ppc = s;
373
+ address_space_init(&port->downstream_as, port->downstream, name);
374
+
375
+ size = memory_region_size(port->downstream);
376
+ memory_region_init_io(&port->upstream, obj, &tz_ppc_ops,
377
+ port, name, size);
378
+ sysbus_init_mmio(sbd, &port->upstream);
379
+ g_free(name);
380
+ }
381
+}
382
+
383
+static const VMStateDescription tz_ppc_vmstate = {
384
+ .name = "tz-ppc",
385
+ .version_id = 1,
386
+ .minimum_version_id = 1,
387
+ .fields = (VMStateField[]) {
388
+ VMSTATE_BOOL_ARRAY(cfg_nonsec, TZPPC, 16),
389
+ VMSTATE_BOOL_ARRAY(cfg_ap, TZPPC, 16),
390
+ VMSTATE_BOOL(cfg_sec_resp, TZPPC),
391
+ VMSTATE_BOOL(irq_enable, TZPPC),
392
+ VMSTATE_BOOL(irq_clear, TZPPC),
393
+ VMSTATE_BOOL(irq_status, TZPPC),
394
+ VMSTATE_END_OF_LIST()
395
+ }
396
+};
397
+
398
+#define DEFINE_PORT(N) \
399
+ DEFINE_PROP_LINK("port[" #N "]", TZPPC, port[N].downstream, \
400
+ TYPE_MEMORY_REGION, MemoryRegion *)
401
+
402
+static Property tz_ppc_properties[] = {
403
+ DEFINE_PROP_UINT32("NONSEC_MASK", TZPPC, nonsec_mask, 0),
404
+ DEFINE_PORT(0),
405
+ DEFINE_PORT(1),
406
+ DEFINE_PORT(2),
407
+ DEFINE_PORT(3),
408
+ DEFINE_PORT(4),
409
+ DEFINE_PORT(5),
410
+ DEFINE_PORT(6),
411
+ DEFINE_PORT(7),
412
+ DEFINE_PORT(8),
413
+ DEFINE_PORT(9),
414
+ DEFINE_PORT(10),
415
+ DEFINE_PORT(11),
416
+ DEFINE_PORT(12),
417
+ DEFINE_PORT(13),
418
+ DEFINE_PORT(14),
419
+ DEFINE_PORT(15),
420
+ DEFINE_PROP_END_OF_LIST(),
421
+};
422
+
423
+static void tz_ppc_class_init(ObjectClass *klass, void *data)
424
+{
425
+ DeviceClass *dc = DEVICE_CLASS(klass);
426
+
427
+ dc->realize = tz_ppc_realize;
428
+ dc->vmsd = &tz_ppc_vmstate;
429
+ dc->reset = tz_ppc_reset;
430
+ dc->props = tz_ppc_properties;
431
+}
432
+
433
+static const TypeInfo tz_ppc_info = {
434
+ .name = TYPE_TZ_PPC,
435
+ .parent = TYPE_SYS_BUS_DEVICE,
436
+ .instance_size = sizeof(TZPPC),
437
+ .instance_init = tz_ppc_init,
438
+ .class_init = tz_ppc_class_init,
439
+};
440
+
441
+static void tz_ppc_register_types(void)
442
+{
443
+ type_register_static(&tz_ppc_info);
444
+}
445
+
446
+type_init(tz_ppc_register_types);
447
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
448
index XXXXXXX..XXXXXXX 100644
449
--- a/default-configs/arm-softmmu.mak
450
+++ b/default-configs/arm-softmmu.mak
451
@@ -XXX,XX +XXX,XX @@ CONFIG_CMSDK_APB_UART=y
452
CONFIG_MPS2_FPGAIO=y
453
CONFIG_MPS2_SCC=y
454
455
+CONFIG_TZ_PPC=y
456
+
457
CONFIG_VERSATILE_PCI=y
458
CONFIG_VERSATILE_I2C=y
459
460
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
461
index XXXXXXX..XXXXXXX 100644
462
--- a/hw/misc/trace-events
463
+++ b/hw/misc/trace-events
464
@@ -XXX,XX +XXX,XX @@ mos6522_get_next_irq_time(uint16_t latch, int64_t d, int64_t delta) "latch=%d co
465
mos6522_set_sr_int(void) "set sr_int"
466
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
467
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
468
+
469
+# hw/misc/tz-ppc.c
470
+tz_ppc_reset(void) "TZ PPC: reset"
471
+tz_ppc_cfg_nonsec(int n, int level) "TZ PPC: cfg_nonsec[%d] = %d"
472
+tz_ppc_cfg_ap(int n, int level) "TZ PPC: cfg_ap[%d] = %d"
473
+tz_ppc_cfg_sec_resp(int level) "TZ PPC: cfg_sec_resp = %d"
474
+tz_ppc_irq_enable(int level) "TZ PPC: int_enable = %d"
475
+tz_ppc_irq_clear(int level) "TZ PPC: int_clear = %d"
476
+tz_ppc_update_irq(int level) "TZ PPC: setting irq line to %d"
477
+tz_ppc_read_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " read (secure %d user %d) blocked"
478
+tz_ppc_write_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " write (secure %d user %d) blocked"
479
--
101
--
480
2.16.2
102
2.20.1
481
103
482
104
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
Enable it for the "any" CPU used by *-linux-user.
3
Convert all sid printouts to sid=0x%x.
4
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Message-id: 20180228193125.20577-17-richard.henderson@linaro.org
7
Message-id: 20210309102742.30442-8-eric.auger@redhat.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
9
---
10
target/arm/cpu.c | 1 +
10
hw/arm/trace-events | 24 ++++++++++++------------
11
target/arm/cpu64.c | 1 +
11
1 file changed, 12 insertions(+), 12 deletions(-)
12
2 files changed, 2 insertions(+)
13
12
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
15
--- a/hw/arm/trace-events
17
+++ b/target/arm/cpu.c
16
+++ b/hw/arm/trace-events
18
@@ -XXX,XX +XXX,XX @@ static void arm_any_initfn(Object *obj)
17
@@ -XXX,XX +XXX,XX @@ smmuv3_cmdq_opcode(const char *opcode) "<--- %s"
19
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
18
smmuv3_cmdq_consume_out(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "prod:%d, cons:%d, prod_wrap:%d, cons_wrap:%d "
20
set_feature(&cpu->env, ARM_FEATURE_CRC);
19
smmuv3_cmdq_consume_error(const char *cmd_name, uint8_t cmd_error) "Error on %s command execution: %d"
21
set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
20
smmuv3_write_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)"
22
+ set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
21
-smmuv3_record_event(const char *type, uint32_t sid) "%s sid=%d"
23
cpu->midr = 0xffffffff;
22
-smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "SID:0x%x features:0x%x, sid_split:0x%x"
24
}
23
+smmuv3_record_event(const char *type, uint32_t sid) "%s sid=0x%x"
25
#endif
24
+smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "sid=0x%x features:0x%x, sid_split:0x%x"
26
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
25
smmuv3_find_ste_2lvl(uint64_t strtab_base, uint64_t l1ptr, int l1_ste_offset, uint64_t l2ptr, int l2_ste_offset, int max_l2_ste) "strtab_base:0x%"PRIx64" l1ptr:0x%"PRIx64" l1_off:0x%x, l2ptr:0x%"PRIx64" l2_off:0x%x max_l2_ste:%d"
27
index XXXXXXX..XXXXXXX 100644
26
smmuv3_get_ste(uint64_t addr) "STE addr: 0x%"PRIx64
28
--- a/target/arm/cpu64.c
27
-smmuv3_translate_disable(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=%d bypass (smmu disabled) iova:0x%"PRIx64" is_write=%d"
29
+++ b/target/arm/cpu64.c
28
-smmuv3_translate_bypass(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=%d STE bypass iova:0x%"PRIx64" is_write=%d"
30
@@ -XXX,XX +XXX,XX @@ static void aarch64_any_initfn(Object *obj)
29
-smmuv3_translate_abort(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=%d abort on iova:0x%"PRIx64" is_write=%d"
31
set_feature(&cpu->env, ARM_FEATURE_CRC);
30
-smmuv3_translate_success(const char *n, uint16_t sid, uint64_t iova, uint64_t translated, int perm) "%s sid=%d iova=0x%"PRIx64" translated=0x%"PRIx64" perm=0x%x"
32
set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
31
+smmuv3_translate_disable(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=0x%x bypass (smmu disabled) iova:0x%"PRIx64" is_write=%d"
33
set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
32
+smmuv3_translate_bypass(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=0x%x STE bypass iova:0x%"PRIx64" is_write=%d"
34
+ set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
33
+smmuv3_translate_abort(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=0x%x abort on iova:0x%"PRIx64" is_write=%d"
35
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
34
+smmuv3_translate_success(const char *n, uint16_t sid, uint64_t iova, uint64_t translated, int perm) "%s sid=0x%x iova=0x%"PRIx64" translated=0x%"PRIx64" perm=0x%x"
36
cpu->dcz_blocksize = 7; /* 512 bytes */
35
smmuv3_get_cd(uint64_t addr) "CD addr: 0x%"PRIx64
37
}
36
smmuv3_decode_cd(uint32_t oas) "oas=%d"
37
smmuv3_decode_cd_tt(int i, uint32_t tsz, uint64_t ttb, uint32_t granule_sz, bool had) "TT[%d]:tsz:%d ttb:0x%"PRIx64" granule_sz:%d had:%d"
38
-smmuv3_cmdq_cfgi_ste(int streamid) "streamid =%d"
39
+smmuv3_cmdq_cfgi_ste(int streamid) "streamid= 0x%x"
40
smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%x - end=0x%x"
41
-smmuv3_cmdq_cfgi_cd(uint32_t sid) "streamid = %d"
42
-smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid %d (hits=%d, misses=%d, hit rate=%d)"
43
-smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid %d (hits=%d, misses=%d, hit rate=%d)"
44
-smmuv3_s1_range_inval(int vmid, int asid, uint64_t addr, uint8_t tg, uint64_t num_pages, uint8_t ttl, bool leaf) "vmid =%d asid =%d addr=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" ttl=%d leaf=%d"
45
+smmuv3_cmdq_cfgi_cd(uint32_t sid) "sid=0x%x"
46
+smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid=0x%x (hits=%d, misses=%d, hit rate=%d)"
47
+smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid=0x%x (hits=%d, misses=%d, hit rate=%d)"
48
+smmuv3_s1_range_inval(int vmid, int asid, uint64_t addr, uint8_t tg, uint64_t num_pages, uint8_t ttl, bool leaf) "vmid=%d asid=%d addr=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" ttl=%d leaf=%d"
49
smmuv3_cmdq_tlbi_nh(void) ""
50
smmuv3_cmdq_tlbi_nh_asid(uint16_t asid) "asid=%d"
51
-smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid %d"
52
+smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid=0x%x"
53
smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s"
54
smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s"
55
smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint64_t iova, uint8_t tg, uint64_t num_pages) "iommu mr=%s asid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64
38
--
56
--
39
2.16.2
57
2.20.1
40
58
41
59
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Not enabled anywhere yet.
3
Missed out on compressing the second half of a predicate
4
with length vl % 512 > 256.
4
5
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Adjust all of the x + (y << s) to x | (y << s) as a
7
general style fix. Drop the extract64 because the input
8
uint64_t are known to be already zero-extended from the
9
current size of the predicate.
10
11
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180228193125.20577-11-richard.henderson@linaro.org
13
Message-id: 20210309155305.11301-2-richard.henderson@linaro.org
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
16
---
10
target/arm/cpu.h | 1 +
17
target/arm/sve_helper.c | 30 +++++++++++++++++++++---------
11
linux-user/elfload.c | 1 +
18
1 file changed, 21 insertions(+), 9 deletions(-)
12
2 files changed, 2 insertions(+)
13
19
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
15
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
22
--- a/target/arm/sve_helper.c
17
+++ b/target/arm/cpu.h
23
+++ b/target/arm/sve_helper.c
18
@@ -XXX,XX +XXX,XX @@ enum arm_features {
24
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_uzp_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
19
ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
25
if (oprsz <= 8) {
20
ARM_FEATURE_V8_RDM, /* implements v8.1 simd round multiply */
26
l = compress_bits(n[0] >> odd, esz);
21
ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
27
h = compress_bits(m[0] >> odd, esz);
22
+ ARM_FEATURE_V8_FCMA, /* has complex number part of v8.3 extensions. */
28
- d[0] = extract64(l + (h << (4 * oprsz)), 0, 8 * oprsz);
23
};
29
+ d[0] = l | (h << (4 * oprsz));
24
30
} else {
25
static inline int arm_feature(CPUARMState *env, int feature)
31
ARMPredicateReg tmp_m;
26
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
32
intptr_t oprsz_16 = oprsz / 16;
27
index XXXXXXX..XXXXXXX 100644
33
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_uzp_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
28
--- a/linux-user/elfload.c
34
h = n[2 * i + 1];
29
+++ b/linux-user/elfload.c
35
l = compress_bits(l >> odd, esz);
30
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
36
h = compress_bits(h >> odd, esz);
31
GET_FEATURE(ARM_FEATURE_V8_FP16,
37
- d[i] = l + (h << 32);
32
ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
38
+ d[i] = l | (h << 32);
33
GET_FEATURE(ARM_FEATURE_V8_RDM, ARM_HWCAP_A64_ASIMDRDM);
39
}
34
+ GET_FEATURE(ARM_FEATURE_V8_FCMA, ARM_HWCAP_A64_FCMA);
40
35
#undef GET_FEATURE
41
- /* For VL which is not a power of 2, the results from M do not
36
42
- align nicely with the uint64_t for D. Put the aligned results
37
return hwcaps;
43
- from M into TMP_M and then copy it into place afterward. */
44
+ /*
45
+ * For VL which is not a multiple of 512, the results from M do not
46
+ * align nicely with the uint64_t for D. Put the aligned results
47
+ * from M into TMP_M and then copy it into place afterward.
48
+ */
49
if (oprsz & 15) {
50
- d[i] = compress_bits(n[2 * i] >> odd, esz);
51
+ int final_shift = (oprsz & 15) * 2;
52
+
53
+ l = n[2 * i + 0];
54
+ h = n[2 * i + 1];
55
+ l = compress_bits(l >> odd, esz);
56
+ h = compress_bits(h >> odd, esz);
57
+ d[i] = l | (h << final_shift);
58
59
for (i = 0; i < oprsz_16; i++) {
60
l = m[2 * i + 0];
61
h = m[2 * i + 1];
62
l = compress_bits(l >> odd, esz);
63
h = compress_bits(h >> odd, esz);
64
- tmp_m.p[i] = l + (h << 32);
65
+ tmp_m.p[i] = l | (h << 32);
66
}
67
- tmp_m.p[i] = compress_bits(m[2 * i] >> odd, esz);
68
+ l = m[2 * i + 0];
69
+ h = m[2 * i + 1];
70
+ l = compress_bits(l >> odd, esz);
71
+ h = compress_bits(h >> odd, esz);
72
+ tmp_m.p[i] = l | (h << final_shift);
73
74
swap_memmove(vd + oprsz / 2, &tmp_m, oprsz / 2);
75
} else {
76
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_uzp_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
77
h = m[2 * i + 1];
78
l = compress_bits(l >> odd, esz);
79
h = compress_bits(h >> odd, esz);
80
- d[oprsz_16 + i] = l + (h << 32);
81
+ d[oprsz_16 + i] = l | (h << 32);
82
}
83
}
84
}
38
--
85
--
39
2.16.2
86
2.20.1
40
87
41
88
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
3
Wrote too much with low-half zip (zip1) with vl % 512 != 0.
4
5
Adjust all of the x + (y << s) to x | (y << s) as a style fix.
6
7
We only ever have exact overlap between D, M, and N. Therefore
8
we only need a single temporary, and we do not need to check for
9
partial overlap.
10
11
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-9-richard.henderson@linaro.org
13
Message-id: 20210309155305.11301-3-richard.henderson@linaro.org
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
16
---
8
target/arm/translate.c | 46 ++++++++++++++++++++++++++++++++++++++++++----
17
target/arm/sve_helper.c | 25 ++++++++++++++-----------
9
1 file changed, 42 insertions(+), 4 deletions(-)
18
1 file changed, 14 insertions(+), 11 deletions(-)
10
19
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
20
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
12
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
22
--- a/target/arm/sve_helper.c
14
+++ b/target/arm/translate.c
23
+++ b/target/arm/sve_helper.c
15
@@ -XXX,XX +XXX,XX @@ static const char *regnames[] =
24
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_zip_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
16
{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
25
intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
17
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
26
int esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
18
27
intptr_t high = FIELD_EX32(pred_desc, PREDDESC, DATA);
19
+/* Function prototypes for gen_ functions calling Neon helpers. */
28
+ int esize = 1 << esz;
20
+typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
29
uint64_t *d = vd;
21
+ TCGv_i32, TCGv_i32);
30
intptr_t i;
22
+
31
23
/* initialize TCG globals. */
32
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_zip_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
24
void arm_translate_init(void)
33
mm = extract64(mm, high * half, half);
25
{
34
nn = expand_bits(nn, esz);
26
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
35
mm = expand_bits(mm, esz);
27
}
36
- d[0] = nn + (mm << (1 << esz));
28
neon_store_reg64(cpu_V0, rd + pass);
37
+ d[0] = nn | (mm << esize);
29
}
38
} else {
30
-
39
- ARMPredicateReg tmp_n, tmp_m;
31
-
40
+ ARMPredicateReg tmp;
32
break;
41
33
- default: /* 14 and 15 are RESERVED */
42
/* We produce output faster than we consume input.
34
- return 1;
43
Therefore we must be mindful of possible overlap. */
35
+ case 14: /* VQRDMLAH scalar */
44
- if ((vn - vd) < (uintptr_t)oprsz) {
36
+ case 15: /* VQRDMLSH scalar */
45
- vn = memcpy(&tmp_n, vn, oprsz);
37
+ {
46
- }
38
+ NeonGenThreeOpEnvFn *fn;
47
- if ((vm - vd) < (uintptr_t)oprsz) {
39
+
48
- vm = memcpy(&tmp_m, vm, oprsz);
40
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
49
+ if (vd == vn) {
41
+ return 1;
50
+ vn = memcpy(&tmp, vn, oprsz);
42
+ }
51
+ if (vd == vm) {
43
+ if (u && ((rd | rn) & 1)) {
52
+ vm = vn;
44
+ return 1;
53
+ }
45
+ }
54
+ } else if (vd == vm) {
46
+ if (op == 14) {
55
+ vm = memcpy(&tmp, vm, oprsz);
47
+ if (size == 1) {
56
}
48
+ fn = gen_helper_neon_qrdmlah_s16;
57
if (high) {
49
+ } else {
58
high = oprsz >> 1;
50
+ fn = gen_helper_neon_qrdmlah_s32;
59
}
51
+ }
60
52
+ } else {
61
- if ((high & 3) == 0) {
53
+ if (size == 1) {
62
+ if ((oprsz & 7) == 0) {
54
+ fn = gen_helper_neon_qrdmlsh_s16;
63
uint32_t *n = vn, *m = vm;
55
+ } else {
64
high >>= 2;
56
+ fn = gen_helper_neon_qrdmlsh_s32;
65
57
+ }
66
- for (i = 0; i < DIV_ROUND_UP(oprsz, 8); i++) {
58
+ }
67
+ for (i = 0; i < oprsz / 8; i++) {
59
+
68
uint64_t nn = n[H4(high + i)];
60
+ tmp2 = neon_get_scalar(size, rm);
69
uint64_t mm = m[H4(high + i)];
61
+ for (pass = 0; pass < (u ? 4 : 2); pass++) {
70
62
+ tmp = neon_load_reg(rn, pass);
71
nn = expand_bits(nn, esz);
63
+ tmp3 = neon_load_reg(rd, pass);
72
mm = expand_bits(mm, esz);
64
+ fn(tmp, cpu_env, tmp, tmp2, tmp3);
73
- d[i] = nn + (mm << (1 << esz));
65
+ tcg_temp_free_i32(tmp3);
74
+ d[i] = nn | (mm << esize);
66
+ neon_store_reg(rd, pass, tmp);
67
+ }
68
+ tcg_temp_free_i32(tmp2);
69
+ }
70
+ break;
71
+ default:
72
+ g_assert_not_reached();
73
}
74
}
75
}
75
} else { /* size == 3 */
76
} else {
77
uint8_t *n = vn, *m = vm;
78
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_zip_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
79
80
nn = expand_bits(nn, esz);
81
mm = expand_bits(mm, esz);
82
- d16[H2(i)] = nn + (mm << (1 << esz));
83
+ d16[H2(i)] = nn | (mm << esize);
84
}
85
}
86
}
76
--
87
--
77
2.16.2
88
2.20.1
78
89
79
90
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Wrote too much with punpk1 with vl % 512 != 0.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-7-richard.henderson@linaro.org
8
Message-id: 20210309155305.11301-4-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/translate-a64.c | 29 +++++++++++++++++++++++++++++
11
target/arm/sve_helper.c | 4 ++--
9
1 file changed, 29 insertions(+)
12
1 file changed, 2 insertions(+), 2 deletions(-)
10
13
11
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-a64.c
16
--- a/target/arm/sve_helper.c
14
+++ b/target/arm/translate-a64.c
17
+++ b/target/arm/sve_helper.c
15
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_punpk_p)(void *vd, void *vn, uint32_t pred_desc)
16
case 0x19: /* FMULX */
19
high = oprsz >> 1;
17
is_fp = true;
20
}
18
break;
21
19
+ case 0x1d: /* SQRDMLAH */
22
- if ((high & 3) == 0) {
20
+ case 0x1f: /* SQRDMLSH */
23
+ if ((oprsz & 7) == 0) {
21
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
24
uint32_t *n = vn;
22
+ unallocated_encoding(s);
25
high >>= 2;
23
+ return;
26
24
+ }
27
- for (i = 0; i < DIV_ROUND_UP(oprsz, 8); i++) {
25
+ break;
28
+ for (i = 0; i < oprsz / 8; i++) {
26
default:
29
uint64_t nn = n[H4(high + i)];
27
unallocated_encoding(s);
30
d[i] = expand_bits(nn, 0);
28
return;
29
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
30
tcg_op, tcg_idx);
31
}
32
break;
33
+ case 0x1d: /* SQRDMLAH */
34
+ read_vec_element_i32(s, tcg_res, rd, pass,
35
+ is_scalar ? size : MO_32);
36
+ if (size == 1) {
37
+ gen_helper_neon_qrdmlah_s16(tcg_res, cpu_env,
38
+ tcg_op, tcg_idx, tcg_res);
39
+ } else {
40
+ gen_helper_neon_qrdmlah_s32(tcg_res, cpu_env,
41
+ tcg_op, tcg_idx, tcg_res);
42
+ }
43
+ break;
44
+ case 0x1f: /* SQRDMLSH */
45
+ read_vec_element_i32(s, tcg_res, rd, pass,
46
+ is_scalar ? size : MO_32);
47
+ if (size == 1) {
48
+ gen_helper_neon_qrdmlsh_s16(tcg_res, cpu_env,
49
+ tcg_op, tcg_idx, tcg_res);
50
+ } else {
51
+ gen_helper_neon_qrdmlsh_s32(tcg_res, cpu_env,
52
+ tcg_op, tcg_idx, tcg_res);
53
+ }
54
+ break;
55
default:
56
g_assert_not_reached();
57
}
31
}
58
--
32
--
59
2.16.2
33
2.20.1
60
34
61
35
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Happily, the bits are in the same places compared to a32.
3
Since b64ee454a4a0, all predicate operations should be
4
using these field macros for predicates.
4
5
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180228193125.20577-16-richard.henderson@linaro.org
7
Message-id: 20210309155305.11301-5-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
target/arm/translate.c | 14 +++++++++++++-
11
target/arm/sve_helper.c | 6 +++---
11
1 file changed, 13 insertions(+), 1 deletion(-)
12
target/arm/translate-sve.c | 7 +++----
13
2 files changed, 6 insertions(+), 7 deletions(-)
12
14
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
17
--- a/target/arm/sve_helper.c
16
+++ b/target/arm/translate.c
18
+++ b/target/arm/sve_helper.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_compact_d)(void *vd, void *vn, void *vg, uint32_t desc)
18
default_exception_el(s));
20
*/
19
break;
21
int32_t HELPER(sve_last_active_element)(void *vg, uint32_t pred_desc)
20
}
22
{
21
- if (((insn >> 24) & 3) == 3) {
23
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
22
+ if ((insn & 0xfe000a00) == 0xfc000800
24
- intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
23
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
25
+ intptr_t words = DIV_ROUND_UP(FIELD_EX32(pred_desc, PREDDESC, OPRSZ), 8);
24
+ /* The Thumb2 and ARM encodings are identical. */
26
+ intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
25
+ if (disas_neon_insn_3same_ext(s, insn)) {
27
26
+ goto illegal_op;
28
- return last_active_element(vg, DIV_ROUND_UP(oprsz, 8), esz);
27
+ }
29
+ return last_active_element(vg, words, esz);
28
+ } else if ((insn & 0xff000a00) == 0xfe000800
30
}
29
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
31
30
+ /* The Thumb2 and ARM encodings are identical. */
32
void HELPER(sve_splice)(void *vd, void *vn, void *vm, void *vg, uint32_t desc)
31
+ if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
33
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
32
+ goto illegal_op;
34
index XXXXXXX..XXXXXXX 100644
33
+ }
35
--- a/target/arm/translate-sve.c
34
+ } else if (((insn >> 24) & 3) == 3) {
36
+++ b/target/arm/translate-sve.c
35
/* Translate into the equivalent ARM encoding. */
37
@@ -XXX,XX +XXX,XX @@ static void find_last_active(DisasContext *s, TCGv_i32 ret, int esz, int pg)
36
insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
38
*/
37
if (disas_neon_data_insn(s, insn)) {
39
TCGv_ptr t_p = tcg_temp_new_ptr();
40
TCGv_i32 t_desc;
41
- unsigned vsz = pred_full_reg_size(s);
42
- unsigned desc;
43
+ unsigned desc = 0;
44
45
- desc = vsz - 2;
46
- desc = deposit32(desc, SIMD_DATA_SHIFT, 2, esz);
47
+ desc = FIELD_DP32(desc, PREDDESC, OPRSZ, pred_full_reg_size(s));
48
+ desc = FIELD_DP32(desc, PREDDESC, ESZ, esz);
49
50
tcg_gen_addi_ptr(t_p, cpu_env, pred_full_reg_offset(s, pg));
51
t_desc = tcg_const_i32(desc);
38
--
52
--
39
2.16.2
53
2.20.1
40
54
41
55
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Since b64ee454a4a0, all predicate operations should be
4
using these field macros for predicates.
5
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20180228193125.20577-15-richard.henderson@linaro.org
7
Message-id: 20210309155305.11301-6-richard.henderson@linaro.org
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/translate.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++
11
target/arm/sve_helper.c | 30 ++++++++++++++----------------
9
1 file changed, 61 insertions(+)
12
target/arm/translate-sve.c | 4 ++--
13
2 files changed, 16 insertions(+), 18 deletions(-)
10
14
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
12
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
17
--- a/target/arm/sve_helper.c
14
+++ b/target/arm/translate.c
18
+++ b/target/arm/sve_helper.c
15
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ static uint32_t do_zero(ARMPredicateReg *d, intptr_t oprsz)
16
return 0;
20
void HELPER(sve_brkpa)(void *vd, void *vn, void *vm, void *vg,
21
uint32_t pred_desc)
22
{
23
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
24
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
25
if (last_active_pred(vn, vg, oprsz)) {
26
compute_brk_z(vd, vm, vg, oprsz, true);
27
} else {
28
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_brkpa)(void *vd, void *vn, void *vm, void *vg,
29
uint32_t HELPER(sve_brkpas)(void *vd, void *vn, void *vm, void *vg,
30
uint32_t pred_desc)
31
{
32
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
33
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
34
if (last_active_pred(vn, vg, oprsz)) {
35
return compute_brks_z(vd, vm, vg, oprsz, true);
36
} else {
37
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sve_brkpas)(void *vd, void *vn, void *vm, void *vg,
38
void HELPER(sve_brkpb)(void *vd, void *vn, void *vm, void *vg,
39
uint32_t pred_desc)
40
{
41
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
42
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
43
if (last_active_pred(vn, vg, oprsz)) {
44
compute_brk_z(vd, vm, vg, oprsz, false);
45
} else {
46
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_brkpb)(void *vd, void *vn, void *vm, void *vg,
47
uint32_t HELPER(sve_brkpbs)(void *vd, void *vn, void *vm, void *vg,
48
uint32_t pred_desc)
49
{
50
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
51
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
52
if (last_active_pred(vn, vg, oprsz)) {
53
return compute_brks_z(vd, vm, vg, oprsz, false);
54
} else {
55
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sve_brkpbs)(void *vd, void *vn, void *vm, void *vg,
56
57
void HELPER(sve_brka_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
58
{
59
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
60
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
61
compute_brk_z(vd, vn, vg, oprsz, true);
17
}
62
}
18
63
19
+/* Advanced SIMD two registers and a scalar extension.
64
uint32_t HELPER(sve_brkas_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
20
+ * 31 24 23 22 20 16 12 11 10 9 8 3 0
21
+ * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
22
+ * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
23
+ * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
24
+ *
25
+ */
26
+
27
+static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
28
+{
29
+ int rd, rn, rm, rot, size, opr_sz;
30
+ TCGv_ptr fpst;
31
+ bool q;
32
+
33
+ q = extract32(insn, 6, 1);
34
+ VFP_DREG_D(rd, insn);
35
+ VFP_DREG_N(rn, insn);
36
+ VFP_DREG_M(rm, insn);
37
+ if ((rd | rn) & q) {
38
+ return 1;
39
+ }
40
+
41
+ if ((insn & 0xff000f10) == 0xfe000800) {
42
+ /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
43
+ rot = extract32(insn, 20, 2);
44
+ size = extract32(insn, 23, 1);
45
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
46
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
47
+ return 1;
48
+ }
49
+ } else {
50
+ return 1;
51
+ }
52
+
53
+ if (s->fp_excp_el) {
54
+ gen_exception_insn(s, 4, EXCP_UDEF,
55
+ syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
56
+ return 0;
57
+ }
58
+ if (!s->vfp_enabled) {
59
+ return 1;
60
+ }
61
+
62
+ opr_sz = (1 + q) * 8;
63
+ fpst = get_fpstatus_ptr(1);
64
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
65
+ vfp_reg_offset(1, rn),
66
+ vfp_reg_offset(1, rm), fpst,
67
+ opr_sz, opr_sz, rot,
68
+ size ? gen_helper_gvec_fcmlas_idx
69
+ : gen_helper_gvec_fcmlah_idx);
70
+ tcg_temp_free_ptr(fpst);
71
+ return 0;
72
+}
73
+
74
static int disas_coproc_insn(DisasContext *s, uint32_t insn)
75
{
65
{
76
int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
66
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
77
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
67
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
78
goto illegal_op;
68
return compute_brks_z(vd, vn, vg, oprsz, true);
79
}
69
}
80
return;
70
81
+ } else if ((insn & 0x0f000a00) == 0x0e000800
71
void HELPER(sve_brkb_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
82
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
72
{
83
+ if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
73
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
84
+ goto illegal_op;
74
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
85
+ }
75
compute_brk_z(vd, vn, vg, oprsz, false);
86
+ return;
76
}
87
} else if ((insn & 0x0fe00000) == 0x0c400000) {
77
88
/* Coprocessor double register transfer. */
78
uint32_t HELPER(sve_brkbs_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
89
ARCH(5TE);
79
{
80
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
81
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
82
return compute_brks_z(vd, vn, vg, oprsz, false);
83
}
84
85
void HELPER(sve_brka_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
86
{
87
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
88
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
89
compute_brk_m(vd, vn, vg, oprsz, true);
90
}
91
92
uint32_t HELPER(sve_brkas_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
93
{
94
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
95
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
96
return compute_brks_m(vd, vn, vg, oprsz, true);
97
}
98
99
void HELPER(sve_brkb_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
100
{
101
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
102
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
103
compute_brk_m(vd, vn, vg, oprsz, false);
104
}
105
106
uint32_t HELPER(sve_brkbs_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
107
{
108
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
109
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
110
return compute_brks_m(vd, vn, vg, oprsz, false);
111
}
112
113
void HELPER(sve_brkn)(void *vd, void *vn, void *vg, uint32_t pred_desc)
114
{
115
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
116
-
117
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
118
if (!last_active_pred(vn, vg, oprsz)) {
119
do_zero(vd, oprsz);
120
}
121
@@ -XXX,XX +XXX,XX @@ static uint32_t predtest_ones(ARMPredicateReg *d, intptr_t oprsz,
122
123
uint32_t HELPER(sve_brkns)(void *vd, void *vn, void *vg, uint32_t pred_desc)
124
{
125
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
126
-
127
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
128
if (last_active_pred(vn, vg, oprsz)) {
129
return predtest_ones(vd, oprsz, -1);
130
} else {
131
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/target/arm/translate-sve.c
134
+++ b/target/arm/translate-sve.c
135
@@ -XXX,XX +XXX,XX @@ static bool do_brk3(DisasContext *s, arg_rprr_s *a,
136
TCGv_ptr n = tcg_temp_new_ptr();
137
TCGv_ptr m = tcg_temp_new_ptr();
138
TCGv_ptr g = tcg_temp_new_ptr();
139
- TCGv_i32 t = tcg_const_i32(vsz - 2);
140
+ TCGv_i32 t = tcg_const_i32(FIELD_DP32(0, PREDDESC, OPRSZ, vsz));
141
142
tcg_gen_addi_ptr(d, cpu_env, pred_full_reg_offset(s, a->rd));
143
tcg_gen_addi_ptr(n, cpu_env, pred_full_reg_offset(s, a->rn));
144
@@ -XXX,XX +XXX,XX @@ static bool do_brk2(DisasContext *s, arg_rpr_s *a,
145
TCGv_ptr d = tcg_temp_new_ptr();
146
TCGv_ptr n = tcg_temp_new_ptr();
147
TCGv_ptr g = tcg_temp_new_ptr();
148
- TCGv_i32 t = tcg_const_i32(vsz - 2);
149
+ TCGv_i32 t = tcg_const_i32(FIELD_DP32(0, PREDDESC, OPRSZ, vsz));
150
151
tcg_gen_addi_ptr(d, cpu_env, pred_full_reg_offset(s, a->rd));
152
tcg_gen_addi_ptr(n, cpu_env, pred_full_reg_offset(s, a->rn));
90
--
153
--
91
2.16.2
154
2.20.1
92
155
93
156
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Enable it for the "any" CPU used by *-linux-user.
3
Since b64ee454a4a0, all predicate operations should be
4
using these field macros for predicates.
4
5
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210309155305.11301-7-richard.henderson@linaro.org
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20180228193125.20577-10-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
target/arm/cpu.c | 1 +
11
target/arm/sve_helper.c | 6 +++---
11
target/arm/cpu64.c | 1 +
12
target/arm/translate-sve.c | 6 +++---
12
2 files changed, 2 insertions(+)
13
2 files changed, 6 insertions(+), 6 deletions(-)
13
14
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
17
--- a/target/arm/sve_helper.c
17
+++ b/target/arm/cpu.c
18
+++ b/target/arm/sve_helper.c
18
@@ -XXX,XX +XXX,XX @@ static void arm_any_initfn(Object *obj)
19
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sve_brkns)(void *vd, void *vn, void *vg, uint32_t pred_desc)
19
set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
20
20
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
21
uint64_t HELPER(sve_cntp)(void *vn, void *vg, uint32_t pred_desc)
21
set_feature(&cpu->env, ARM_FEATURE_CRC);
22
{
22
+ set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
23
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
23
cpu->midr = 0xffffffff;
24
- intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
24
}
25
+ intptr_t words = DIV_ROUND_UP(FIELD_EX32(pred_desc, PREDDESC, OPRSZ), 8);
25
#endif
26
+ intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
26
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
27
uint64_t *n = vn, *g = vg, sum = 0, mask = pred_esz_masks[esz];
28
intptr_t i;
29
30
- for (i = 0; i < DIV_ROUND_UP(oprsz, 8); ++i) {
31
+ for (i = 0; i < words; ++i) {
32
uint64_t t = n[i] & g[i] & mask;
33
sum += ctpop64(t);
34
}
35
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
27
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu64.c
37
--- a/target/arm/translate-sve.c
29
+++ b/target/arm/cpu64.c
38
+++ b/target/arm/translate-sve.c
30
@@ -XXX,XX +XXX,XX @@ static void aarch64_any_initfn(Object *obj)
39
@@ -XXX,XX +XXX,XX @@ static void do_cntp(DisasContext *s, TCGv_i64 val, int esz, int pn, int pg)
31
set_feature(&cpu->env, ARM_FEATURE_V8_SM4);
40
} else {
32
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
41
TCGv_ptr t_pn = tcg_temp_new_ptr();
33
set_feature(&cpu->env, ARM_FEATURE_CRC);
42
TCGv_ptr t_pg = tcg_temp_new_ptr();
34
+ set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
43
- unsigned desc;
35
set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
44
+ unsigned desc = 0;
36
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
45
TCGv_i32 t_desc;
37
cpu->dcz_blocksize = 7; /* 512 bytes */
46
47
- desc = psz - 2;
48
- desc = deposit32(desc, SIMD_DATA_SHIFT, 2, esz);
49
+ desc = FIELD_DP32(desc, PREDDESC, OPRSZ, psz);
50
+ desc = FIELD_DP32(desc, PREDDESC, ESZ, esz);
51
52
tcg_gen_addi_ptr(t_pn, cpu_env, pred_full_reg_offset(s, pn));
53
tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg));
38
--
54
--
39
2.16.2
55
2.20.1
40
56
41
57
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Include the U bit in the switches rather than testing separately.
3
Since b64ee454a4a0, all predicate operations should be
4
using these field macros for predicates.
4
5
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210309155305.11301-8-richard.henderson@linaro.org
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20180228193125.20577-3-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
target/arm/translate-a64.c | 129 +++++++++++++++++++++------------------------
11
target/arm/sve_helper.c | 4 ++--
11
1 file changed, 61 insertions(+), 68 deletions(-)
12
target/arm/translate-sve.c | 7 ++++---
13
2 files changed, 6 insertions(+), 5 deletions(-)
12
14
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
17
--- a/target/arm/sve_helper.c
16
+++ b/target/arm/translate-a64.c
18
+++ b/target/arm/sve_helper.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(sve_cntp)(void *vn, void *vg, uint32_t pred_desc)
18
int index;
20
19
TCGv_ptr fpst;
21
uint32_t HELPER(sve_while)(void *vd, uint32_t count, uint32_t pred_desc)
20
22
{
21
- switch (opcode) {
23
- uintptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
22
- case 0x0: /* MLA */
24
- intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
23
- case 0x4: /* MLS */
25
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
24
- if (!u || is_scalar) {
26
+ intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
25
+ switch (16 * u + opcode) {
27
uint64_t esz_mask = pred_esz_masks[esz];
26
+ case 0x08: /* MUL */
28
ARMPredicateReg *d = vd;
27
+ case 0x10: /* MLA */
29
uint32_t flags;
28
+ case 0x14: /* MLS */
30
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
29
+ if (is_scalar) {
31
index XXXXXXX..XXXXXXX 100644
30
unallocated_encoding(s);
32
--- a/target/arm/translate-sve.c
31
return;
33
+++ b/target/arm/translate-sve.c
32
}
34
@@ -XXX,XX +XXX,XX @@ static bool trans_WHILE(DisasContext *s, arg_WHILE *a)
33
break;
35
TCGv_i64 op0, op1, t0, t1, tmax;
34
- case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
36
TCGv_i32 t2, t3;
35
- case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
37
TCGv_ptr ptr;
36
- case 0xa: /* SMULL, SMULL2, UMULL, UMULL2 */
38
- unsigned desc, vsz = vec_full_reg_size(s);
37
+ case 0x02: /* SMLAL, SMLAL2 */
39
+ unsigned vsz = vec_full_reg_size(s);
38
+ case 0x12: /* UMLAL, UMLAL2 */
40
+ unsigned desc = 0;
39
+ case 0x06: /* SMLSL, SMLSL2 */
41
TCGCond cond;
40
+ case 0x16: /* UMLSL, UMLSL2 */
42
41
+ case 0x0a: /* SMULL, SMULL2 */
43
if (!sve_access_check(s)) {
42
+ case 0x1a: /* UMULL, UMULL2 */
44
@@ -XXX,XX +XXX,XX @@ static bool trans_WHILE(DisasContext *s, arg_WHILE *a)
43
if (is_scalar) {
45
/* Scale elements to bits. */
44
unallocated_encoding(s);
46
tcg_gen_shli_i32(t2, t2, a->esz);
45
return;
47
46
}
48
- desc = (vsz / 8) - 2;
47
is_long = true;
49
- desc = deposit32(desc, SIMD_DATA_SHIFT, 2, a->esz);
48
break;
50
+ desc = FIELD_DP32(desc, PREDDESC, OPRSZ, vsz / 8);
49
- case 0x3: /* SQDMLAL, SQDMLAL2 */
51
+ desc = FIELD_DP32(desc, PREDDESC, ESZ, a->esz);
50
- case 0x7: /* SQDMLSL, SQDMLSL2 */
52
t3 = tcg_const_i32(desc);
51
- case 0xb: /* SQDMULL, SQDMULL2 */
53
52
+ case 0x03: /* SQDMLAL, SQDMLAL2 */
54
ptr = tcg_temp_new_ptr();
53
+ case 0x07: /* SQDMLSL, SQDMLSL2 */
54
+ case 0x0b: /* SQDMULL, SQDMULL2 */
55
is_long = true;
56
- /* fall through */
57
- case 0xc: /* SQDMULH */
58
- case 0xd: /* SQRDMULH */
59
- if (u) {
60
- unallocated_encoding(s);
61
- return;
62
- }
63
break;
64
- case 0x8: /* MUL */
65
- if (u || is_scalar) {
66
- unallocated_encoding(s);
67
- return;
68
- }
69
+ case 0x0c: /* SQDMULH */
70
+ case 0x0d: /* SQRDMULH */
71
break;
72
- case 0x1: /* FMLA */
73
- case 0x5: /* FMLS */
74
- if (u) {
75
- unallocated_encoding(s);
76
- return;
77
- }
78
- /* fall through */
79
- case 0x9: /* FMUL, FMULX */
80
+ case 0x01: /* FMLA */
81
+ case 0x05: /* FMLS */
82
+ case 0x09: /* FMUL */
83
+ case 0x19: /* FMULX */
84
if (size == 1) {
85
unallocated_encoding(s);
86
return;
87
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
88
89
read_vec_element(s, tcg_op, rn, pass, MO_64);
90
91
- switch (opcode) {
92
- case 0x5: /* FMLS */
93
+ switch (16 * u + opcode) {
94
+ case 0x05: /* FMLS */
95
/* As usual for ARM, separate negation for fused multiply-add */
96
gen_helper_vfp_negd(tcg_op, tcg_op);
97
/* fall through */
98
- case 0x1: /* FMLA */
99
+ case 0x01: /* FMLA */
100
read_vec_element(s, tcg_res, rd, pass, MO_64);
101
gen_helper_vfp_muladdd(tcg_res, tcg_op, tcg_idx, tcg_res, fpst);
102
break;
103
- case 0x9: /* FMUL, FMULX */
104
- if (u) {
105
- gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst);
106
- } else {
107
- gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst);
108
- }
109
+ case 0x09: /* FMUL */
110
+ gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst);
111
+ break;
112
+ case 0x19: /* FMULX */
113
+ gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst);
114
break;
115
default:
116
g_assert_not_reached();
117
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
118
119
read_vec_element_i32(s, tcg_op, rn, pass, is_scalar ? size : MO_32);
120
121
- switch (opcode) {
122
- case 0x0: /* MLA */
123
- case 0x4: /* MLS */
124
- case 0x8: /* MUL */
125
+ switch (16 * u + opcode) {
126
+ case 0x08: /* MUL */
127
+ case 0x10: /* MLA */
128
+ case 0x14: /* MLS */
129
{
130
static NeonGenTwoOpFn * const fns[2][2] = {
131
{ gen_helper_neon_add_u16, gen_helper_neon_sub_u16 },
132
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
133
genfn(tcg_res, tcg_op, tcg_res);
134
break;
135
}
136
- case 0x5: /* FMLS */
137
- case 0x1: /* FMLA */
138
+ case 0x05: /* FMLS */
139
+ case 0x01: /* FMLA */
140
read_vec_element_i32(s, tcg_res, rd, pass,
141
is_scalar ? size : MO_32);
142
switch (size) {
143
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
144
g_assert_not_reached();
145
}
146
break;
147
- case 0x9: /* FMUL, FMULX */
148
+ case 0x09: /* FMUL */
149
switch (size) {
150
case 1:
151
- if (u) {
152
- if (is_scalar) {
153
- gen_helper_advsimd_mulxh(tcg_res, tcg_op,
154
- tcg_idx, fpst);
155
- } else {
156
- gen_helper_advsimd_mulx2h(tcg_res, tcg_op,
157
- tcg_idx, fpst);
158
- }
159
+ if (is_scalar) {
160
+ gen_helper_advsimd_mulh(tcg_res, tcg_op,
161
+ tcg_idx, fpst);
162
} else {
163
- if (is_scalar) {
164
- gen_helper_advsimd_mulh(tcg_res, tcg_op,
165
- tcg_idx, fpst);
166
- } else {
167
- gen_helper_advsimd_mul2h(tcg_res, tcg_op,
168
- tcg_idx, fpst);
169
- }
170
+ gen_helper_advsimd_mul2h(tcg_res, tcg_op,
171
+ tcg_idx, fpst);
172
}
173
break;
174
case 2:
175
- if (u) {
176
- gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
177
- } else {
178
- gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
179
- }
180
+ gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
181
break;
182
default:
183
g_assert_not_reached();
184
}
185
break;
186
- case 0xc: /* SQDMULH */
187
+ case 0x19: /* FMULX */
188
+ switch (size) {
189
+ case 1:
190
+ if (is_scalar) {
191
+ gen_helper_advsimd_mulxh(tcg_res, tcg_op,
192
+ tcg_idx, fpst);
193
+ } else {
194
+ gen_helper_advsimd_mulx2h(tcg_res, tcg_op,
195
+ tcg_idx, fpst);
196
+ }
197
+ break;
198
+ case 2:
199
+ gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
200
+ break;
201
+ default:
202
+ g_assert_not_reached();
203
+ }
204
+ break;
205
+ case 0x0c: /* SQDMULH */
206
if (size == 1) {
207
gen_helper_neon_qdmulh_s16(tcg_res, cpu_env,
208
tcg_op, tcg_idx);
209
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
210
tcg_op, tcg_idx);
211
}
212
break;
213
- case 0xd: /* SQRDMULH */
214
+ case 0x0d: /* SQRDMULH */
215
if (size == 1) {
216
gen_helper_neon_qrdmulh_s16(tcg_res, cpu_env,
217
tcg_op, tcg_idx);
218
--
55
--
219
2.16.2
56
2.20.1
220
57
221
58
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Allow the translate subroutines to return false for invalid insns.
3
With the reduction operations, we intentionally increase maxsz to
4
the next power of 2, so as to fill out the reduction tree correctly.
5
Since e2e7168a214b, oprsz must equal maxsz, with exceptions for small
6
vectors, so this triggers an assertion for vector sizes > 32 that are
7
not themselves a power of 2.
4
8
5
At present we can of course invoke an invalid insn exception from within
9
Pass the power-of-two value in the simd_data field instead.
6
the translate subroutine, but in the short term this consolidates code.
7
In the long term it would allow the decodetree language to support
8
overlapping patterns for ISA extensions.
9
10
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180227232618.2908-1-richard.henderson@linaro.org
12
Message-id: 20210309155305.11301-9-richard.henderson@linaro.org
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
---
15
scripts/decodetree.py | 5 ++---
16
target/arm/sve_helper.c | 2 +-
16
1 file changed, 2 insertions(+), 3 deletions(-)
17
target/arm/translate-sve.c | 2 +-
18
2 files changed, 2 insertions(+), 2 deletions(-)
17
19
18
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
20
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
19
index XXXXXXX..XXXXXXX 100755
21
index XXXXXXX..XXXXXXX 100644
20
--- a/scripts/decodetree.py
22
--- a/target/arm/sve_helper.c
21
+++ b/scripts/decodetree.py
23
+++ b/target/arm/sve_helper.c
22
@@ -XXX,XX +XXX,XX @@ class Pattern(General):
24
@@ -XXX,XX +XXX,XX @@ static TYPE NAME##_reduce(TYPE *data, float_status *status, uintptr_t n) \
23
global translate_prefix
25
} \
24
output('typedef ', self.base.base.struct_name(),
26
uint64_t HELPER(NAME)(void *vn, void *vg, void *vs, uint32_t desc) \
25
' arg_', self.name, ';\n')
27
{ \
26
- output(translate_scope, 'void ', translate_prefix, '_', self.name,
28
- uintptr_t i, oprsz = simd_oprsz(desc), maxsz = simd_maxsz(desc); \
27
+ output(translate_scope, 'bool ', translate_prefix, '_', self.name,
29
+ uintptr_t i, oprsz = simd_oprsz(desc), maxsz = simd_data(desc); \
28
'(DisasContext *ctx, arg_', self.name,
30
TYPE data[sizeof(ARMVectorReg) / sizeof(TYPE)]; \
29
' *a, ', insntype, ' insn);\n')
31
for (i = 0; i < oprsz; ) { \
30
32
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
31
@@ -XXX,XX +XXX,XX @@ class Pattern(General):
33
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
32
output(ind, self.base.extract_name(), '(&u.f_', arg, ', insn);\n')
34
index XXXXXXX..XXXXXXX 100644
33
for n, f in self.fields.items():
35
--- a/target/arm/translate-sve.c
34
output(ind, 'u.f_', arg, '.', n, ' = ', f.str_extract(), ';\n')
36
+++ b/target/arm/translate-sve.c
35
- output(ind, translate_prefix, '_', self.name,
37
@@ -XXX,XX +XXX,XX @@ static void do_reduce(DisasContext *s, arg_rpr_esz *a,
36
+ output(ind, 'return ', translate_prefix, '_', self.name,
38
{
37
'(ctx, &u.f_', arg, ', insn);\n')
39
unsigned vsz = vec_full_reg_size(s);
38
- output(ind, 'return true;\n')
40
unsigned p2vsz = pow2ceil(vsz);
39
# end Pattern
41
- TCGv_i32 t_desc = tcg_const_i32(simd_desc(vsz, p2vsz, 0));
40
42
+ TCGv_i32 t_desc = tcg_const_i32(simd_desc(vsz, vsz, p2vsz));
43
TCGv_ptr t_zn, t_pg, status;
44
TCGv_i64 temp;
41
45
42
--
46
--
43
2.16.2
47
2.20.1
44
48
45
49
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Currently the emulated EMAC for sun8i always traverses the transmit queue
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
from the head when transferring packets. It searches for a list of consecutive
5
Message-id: 20180228193125.20577-6-richard.henderson@linaro.org
5
descriptors whichs are flagged as ready for processing and transmits their payloads
6
accordingly. The controller stops processing once it finds a descriptor that is not
7
marked ready.
8
9
While the above behaviour works in most situations, it is not the same as the actual
10
EMAC in hardware. Actual hardware uses the TX_CUR_DESC register value to keep track
11
of the last position in the transmit queue and continues processing from that position
12
when software triggers the start of DMA processing. The currently emulated behaviour can
13
lead to packet loss on transmit when software fills the transmit queue with ready
14
descriptors that overlap the tail of the circular list.
15
16
This commit modifies the emulated EMAC for sun8i such that it processes
17
the transmit queue using the TX_CUR_DESC register in the same way as hardware.
18
19
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
20
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Message-id: 20210310195820.21950-2-nieklinnenbank@gmail.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
23
---
8
target/arm/helper.h | 9 +++++
24
hw/net/allwinner-sun8i-emac.c | 62 +++++++++++++++++++----------------
9
target/arm/translate-a64.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++
25
1 file changed, 34 insertions(+), 28 deletions(-)
10
target/arm/vec_helper.c | 74 +++++++++++++++++++++++++++++++++++++++++
11
3 files changed, 166 insertions(+)
12
26
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
27
diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c
14
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
29
--- a/hw/net/allwinner-sun8i-emac.c
16
+++ b/target/arm/helper.h
30
+++ b/hw/net/allwinner-sun8i-emac.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(dc_zva, void, env, i64)
31
@@ -XXX,XX +XXX,XX @@ static void allwinner_sun8i_emac_update_irq(AwSun8iEmacState *s)
18
DEF_HELPER_FLAGS_2(neon_pmull_64_lo, TCG_CALL_NO_RWG_SE, i64, i64, i64)
32
qemu_set_irq(s->irq, (s->int_sta & s->int_en) != 0);
19
DEF_HELPER_FLAGS_2(neon_pmull_64_hi, TCG_CALL_NO_RWG_SE, i64, i64, i64)
20
21
+DEF_HELPER_FLAGS_5(gvec_qrdmlah_s16, TCG_CALL_NO_RWG,
22
+ void, ptr, ptr, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s16, TCG_CALL_NO_RWG,
24
+ void, ptr, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_5(gvec_qrdmlah_s32, TCG_CALL_NO_RWG,
26
+ void, ptr, ptr, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s32, TCG_CALL_NO_RWG,
28
+ void, ptr, ptr, ptr, ptr, i32)
29
+
30
#ifdef TARGET_AARCH64
31
#include "helper-a64.h"
32
#endif
33
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/translate-a64.c
36
+++ b/target/arm/translate-a64.c
37
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
38
vec_full_reg_size(s), gvec_op);
39
}
33
}
40
34
41
+/* Expand a 3-operand + env pointer operation using
35
-static uint32_t allwinner_sun8i_emac_next_desc(AwSun8iEmacState *s,
42
+ * an out-of-line helper.
36
- FrameDescriptor *desc,
43
+ */
37
- size_t min_size)
44
+static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
38
+static bool allwinner_sun8i_emac_desc_owned(FrameDescriptor *desc,
45
+ int rn, int rm, gen_helper_gvec_3_ptr *fn)
39
+ size_t min_buf_size)
40
{
41
- uint32_t paddr = desc->next;
42
-
43
- dma_memory_read(&s->dma_as, paddr, desc, sizeof(*desc));
44
-
45
- if ((desc->status & DESC_STATUS_CTL) &&
46
- (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) {
47
- return paddr;
48
- } else {
49
- return 0;
50
- }
51
+ return (desc->status & DESC_STATUS_CTL) && (min_buf_size == 0 ||
52
+ (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_buf_size);
53
}
54
55
-static uint32_t allwinner_sun8i_emac_get_desc(AwSun8iEmacState *s,
56
- FrameDescriptor *desc,
57
- uint32_t start_addr,
58
- size_t min_size)
59
+static void allwinner_sun8i_emac_get_desc(AwSun8iEmacState *s,
60
+ FrameDescriptor *desc,
61
+ uint32_t phys_addr)
46
+{
62
+{
47
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
63
+ dma_memory_read(&s->dma_as, phys_addr, desc, sizeof(*desc));
48
+ vec_full_reg_offset(s, rn),
49
+ vec_full_reg_offset(s, rm), cpu_env,
50
+ is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
51
+}
64
+}
52
+
65
+
53
/* Set ZF and NF based on a 64 bit result. This is alas fiddlier
66
+static uint32_t allwinner_sun8i_emac_next_desc(AwSun8iEmacState *s,
54
* than the 32 bit equivalent.
67
+ FrameDescriptor *desc)
55
*/
56
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
57
clear_vec_high(s, is_q, rd);
58
}
59
60
+/* AdvSIMD three same extra
61
+ * 31 30 29 28 24 23 22 21 20 16 15 14 11 10 9 5 4 0
62
+ * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
63
+ * | 0 | Q | U | 0 1 1 1 0 | size | 0 | Rm | 1 | opcode | 1 | Rn | Rd |
64
+ * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
65
+ */
66
+static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
67
+{
68
+{
68
+ int rd = extract32(insn, 0, 5);
69
+ const uint32_t nxt = desc->next;
69
+ int rn = extract32(insn, 5, 5);
70
+ allwinner_sun8i_emac_get_desc(s, desc, nxt);
70
+ int opcode = extract32(insn, 11, 4);
71
+ return nxt;
71
+ int rm = extract32(insn, 16, 5);
72
+ int size = extract32(insn, 22, 2);
73
+ bool u = extract32(insn, 29, 1);
74
+ bool is_q = extract32(insn, 30, 1);
75
+ int feature;
76
+
77
+ switch (u * 16 + opcode) {
78
+ case 0x10: /* SQRDMLAH (vector) */
79
+ case 0x11: /* SQRDMLSH (vector) */
80
+ if (size != 1 && size != 2) {
81
+ unallocated_encoding(s);
82
+ return;
83
+ }
84
+ feature = ARM_FEATURE_V8_RDM;
85
+ break;
86
+ default:
87
+ unallocated_encoding(s);
88
+ return;
89
+ }
90
+ if (!arm_dc_feature(s, feature)) {
91
+ unallocated_encoding(s);
92
+ return;
93
+ }
94
+ if (!fp_access_check(s)) {
95
+ return;
96
+ }
97
+
98
+ switch (opcode) {
99
+ case 0x0: /* SQRDMLAH (vector) */
100
+ switch (size) {
101
+ case 1:
102
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s16);
103
+ break;
104
+ case 2:
105
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s32);
106
+ break;
107
+ default:
108
+ g_assert_not_reached();
109
+ }
110
+ return;
111
+
112
+ case 0x1: /* SQRDMLSH (vector) */
113
+ switch (size) {
114
+ case 1:
115
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s16);
116
+ break;
117
+ case 2:
118
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s32);
119
+ break;
120
+ default:
121
+ g_assert_not_reached();
122
+ }
123
+ return;
124
+
125
+ default:
126
+ g_assert_not_reached();
127
+ }
128
+}
72
+}
129
+
73
+
130
static void handle_2misc_widening(DisasContext *s, int opcode, bool is_q,
74
+static uint32_t allwinner_sun8i_emac_find_desc(AwSun8iEmacState *s,
131
int size, int rn, int rd)
75
+ FrameDescriptor *desc,
76
+ uint32_t start_addr,
77
+ size_t min_size)
132
{
78
{
133
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn)
79
uint32_t desc_addr = start_addr;
134
static const AArch64DecodeTable data_proc_simd[] = {
80
135
/* pattern , mask , fn */
81
/* Note that the list is a cycle. Last entry points back to the head. */
136
{ 0x0e200400, 0x9f200400, disas_simd_three_reg_same },
82
while (desc_addr != 0) {
137
+ { 0x0e008400, 0x9f208400, disas_simd_three_reg_same_extra },
83
- dma_memory_read(&s->dma_as, desc_addr, desc, sizeof(*desc));
138
{ 0x0e200000, 0x9f200c00, disas_simd_three_reg_diff },
84
+ allwinner_sun8i_emac_get_desc(s, desc, desc_addr);
139
{ 0x0e200800, 0x9f3e0c00, disas_simd_two_reg_misc },
85
140
{ 0x0e300800, 0x9f3e0c00, disas_simd_across_lanes },
86
- if ((desc->status & DESC_STATUS_CTL) &&
141
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
87
- (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) {
142
index XXXXXXX..XXXXXXX 100644
88
+ if (allwinner_sun8i_emac_desc_owned(desc, min_size)) {
143
--- a/target/arm/vec_helper.c
89
return desc_addr;
144
+++ b/target/arm/vec_helper.c
90
} else if (desc->next == start_addr) {
145
@@ -XXX,XX +XXX,XX @@
91
break;
146
92
@@ -XXX,XX +XXX,XX @@ static uint32_t allwinner_sun8i_emac_rx_desc(AwSun8iEmacState *s,
147
#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
93
FrameDescriptor *desc,
148
94
size_t min_size)
149
+static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
95
{
150
+{
96
- return allwinner_sun8i_emac_get_desc(s, desc, s->rx_desc_curr, min_size);
151
+ uint64_t *d = vd + opr_sz;
97
+ return allwinner_sun8i_emac_find_desc(s, desc, s->rx_desc_curr, min_size);
152
+ uintptr_t i;
153
+
154
+ for (i = opr_sz; i < max_sz; i += 8) {
155
+ *d++ = 0;
156
+ }
157
+}
158
+
159
/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
160
static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
161
int16_t src2, int16_t src3)
162
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1,
163
return deposit32(e1, 16, 16, e2);
164
}
98
}
165
99
166
+void HELPER(gvec_qrdmlah_s16)(void *vd, void *vn, void *vm,
100
static uint32_t allwinner_sun8i_emac_tx_desc(AwSun8iEmacState *s,
167
+ void *ve, uint32_t desc)
101
- FrameDescriptor *desc,
168
+{
102
- size_t min_size)
169
+ uintptr_t opr_sz = simd_oprsz(desc);
103
+ FrameDescriptor *desc)
170
+ int16_t *d = vd;
104
{
171
+ int16_t *n = vn;
105
- return allwinner_sun8i_emac_get_desc(s, desc, s->tx_desc_head, min_size);
172
+ int16_t *m = vm;
106
+ allwinner_sun8i_emac_get_desc(s, desc, s->tx_desc_curr);
173
+ CPUARMState *env = ve;
107
+ return s->tx_desc_curr;
174
+ uintptr_t i;
175
+
176
+ for (i = 0; i < opr_sz / 2; ++i) {
177
+ d[i] = inl_qrdmlah_s16(env, n[i], m[i], d[i]);
178
+ }
179
+ clear_tail(d, opr_sz, simd_maxsz(desc));
180
+}
181
+
182
/* Signed saturating rounding doubling multiply-subtract high half, 16-bit */
183
static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
184
int16_t src2, int16_t src3)
185
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1,
186
return deposit32(e1, 16, 16, e2);
187
}
108
}
188
109
189
+void HELPER(gvec_qrdmlsh_s16)(void *vd, void *vn, void *vm,
110
static void allwinner_sun8i_emac_flush_desc(AwSun8iEmacState *s,
190
+ void *ve, uint32_t desc)
111
@@ -XXX,XX +XXX,XX @@ static ssize_t allwinner_sun8i_emac_receive(NetClientState *nc,
191
+{
112
bytes_left -= desc_bytes;
192
+ uintptr_t opr_sz = simd_oprsz(desc);
113
193
+ int16_t *d = vd;
114
/* Move to the next descriptor */
194
+ int16_t *n = vn;
115
- s->rx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc, 64);
195
+ int16_t *m = vm;
116
+ s->rx_desc_curr = allwinner_sun8i_emac_find_desc(s, &desc, desc.next,
196
+ CPUARMState *env = ve;
117
+ AW_SUN8I_EMAC_MIN_PKT_SZ);
197
+ uintptr_t i;
118
if (!s->rx_desc_curr) {
198
+
119
/* Not enough buffer space available */
199
+ for (i = 0; i < opr_sz / 2; ++i) {
120
s->int_sta |= INT_STA_RX_BUF_UA;
200
+ d[i] = inl_qrdmlsh_s16(env, n[i], m[i], d[i]);
121
@@ -XXX,XX +XXX,XX @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s)
201
+ }
122
size_t transmitted = 0;
202
+ clear_tail(d, opr_sz, simd_maxsz(desc));
123
static uint8_t packet_buf[2048];
203
+}
124
204
+
125
- s->tx_desc_curr = allwinner_sun8i_emac_tx_desc(s, &desc, 0);
205
/* Signed saturating rounding doubling multiply-accumulate high half, 32-bit */
126
+ s->tx_desc_curr = allwinner_sun8i_emac_tx_desc(s, &desc);
206
uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
127
207
int32_t src2, int32_t src3)
128
/* Read all transmit descriptors */
208
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
129
- while (s->tx_desc_curr != 0) {
209
return ret;
130
+ while (allwinner_sun8i_emac_desc_owned(&desc, 0)) {
210
}
131
211
132
/* Read from physical memory into packet buffer */
212
+void HELPER(gvec_qrdmlah_s32)(void *vd, void *vn, void *vm,
133
bytes = desc.status2 & DESC_STATUS2_BUF_SIZE_MASK;
213
+ void *ve, uint32_t desc)
134
@@ -XXX,XX +XXX,XX @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s)
214
+{
135
packet_bytes = 0;
215
+ uintptr_t opr_sz = simd_oprsz(desc);
136
transmitted++;
216
+ int32_t *d = vd;
137
}
217
+ int32_t *n = vn;
138
- s->tx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc, 0);
218
+ int32_t *m = vm;
139
+ s->tx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc);
219
+ CPUARMState *env = ve;
220
+ uintptr_t i;
221
+
222
+ for (i = 0; i < opr_sz / 4; ++i) {
223
+ d[i] = helper_neon_qrdmlah_s32(env, n[i], m[i], d[i]);
224
+ }
225
+ clear_tail(d, opr_sz, simd_maxsz(desc));
226
+}
227
+
228
/* Signed saturating rounding doubling multiply-subtract high half, 32-bit */
229
uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
230
int32_t src2, int32_t src3)
231
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
232
}
140
}
233
return ret;
141
234
}
142
/* Raise transmit completed interrupt */
235
+
236
+void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm,
237
+ void *ve, uint32_t desc)
238
+{
239
+ uintptr_t opr_sz = simd_oprsz(desc);
240
+ int32_t *d = vd;
241
+ int32_t *n = vn;
242
+ int32_t *m = vm;
243
+ CPUARMState *env = ve;
244
+ uintptr_t i;
245
+
246
+ for (i = 0; i < opr_sz / 4; ++i) {
247
+ d[i] = helper_neon_qrdmlsh_s32(env, n[i], m[i], d[i]);
248
+ }
249
+ clear_tail(d, opr_sz, simd_maxsz(desc));
250
+}
251
--
143
--
252
2.16.2
144
2.20.1
253
145
254
146
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
The image for Armbian 19.11.3 bionic has been removed from the armbian server.
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Without the image as input the test arm_orangepi_bionic_19_11 cannot run.
5
Message-id: 20180228193125.20577-8-richard.henderson@linaro.org
5
6
This commit removes the test completely and merges the code of the generic function
7
do_test_arm_orangepi_uboot_armbian back with the 20.08 test.
8
9
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
10
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
11
Message-id: 20210310195820.21950-3-nieklinnenbank@gmail.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
13
---
8
target/arm/translate.c | 86 +++++++++++++++++++++++++++++++++++++++-----------
14
tests/acceptance/boot_linux_console.py | 72 ++++++++------------------
9
1 file changed, 67 insertions(+), 19 deletions(-)
15
1 file changed, 23 insertions(+), 49 deletions(-)
10
16
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
19
--- a/tests/acceptance/boot_linux_console.py
14
+++ b/target/arm/translate.c
20
+++ b/tests/acceptance/boot_linux_console.py
15
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_sd(self):
16
#include "disas/disas.h"
22
# Wait for VM to shut down gracefully
17
#include "exec/exec-all.h"
23
self.vm.wait()
18
#include "tcg-op.h"
24
19
+#include "tcg-op-gvec.h"
25
- def do_test_arm_orangepi_uboot_armbian(self, image_path):
20
#include "qemu/log.h"
26
+ @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
21
#include "qemu/bitops.h"
27
+ 'Test artifacts fetched from unreliable apt.armbian.com')
22
#include "arm_ldst.h"
28
+ @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
23
@@ -XXX,XX +XXX,XX @@ static void gen_neon_narrow_op(int op, int u, int size,
29
+ def test_arm_orangepi_bionic_20_08(self):
24
#define NEON_3R_VPMAX 20
30
+ """
25
#define NEON_3R_VPMIN 21
31
+ :avocado: tags=arch:arm
26
#define NEON_3R_VQDMULH_VQRDMULH 22
32
+ :avocado: tags=machine:orangepi-pc
27
-#define NEON_3R_VPADD 23
33
+ :avocado: tags=device:sd
28
+#define NEON_3R_VPADD_VQRDMLAH 23
34
+ """
29
#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
30
-#define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
31
+#define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
32
#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
33
#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
34
#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
35
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_3r_sizes[] = {
36
[NEON_3R_VPMAX] = 0x7,
37
[NEON_3R_VPMIN] = 0x7,
38
[NEON_3R_VQDMULH_VQRDMULH] = 0x6,
39
- [NEON_3R_VPADD] = 0x7,
40
+ [NEON_3R_VPADD_VQRDMLAH] = 0x7,
41
[NEON_3R_SHA] = 0xf, /* size field encodes op type */
42
- [NEON_3R_VFM] = 0x5, /* size bit 1 encodes op */
43
+ [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
44
[NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
45
[NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
46
[NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
47
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_2rm_sizes[] = {
48
[NEON_2RM_VCVT_UF] = 0x4,
49
};
50
51
+
35
+
52
+/* Expand v8.1 simd helper. */
36
+ # This test download a 275 MiB compressed image and expand it
53
+static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
37
+ # to 1036 MiB, but the underlying filesystem is 1552 MiB...
54
+ int q, int rd, int rn, int rm)
38
+ # As we expand it to 2 GiB we are safe.
55
+{
56
+ if (arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
57
+ int opr_sz = (1 + q) * 8;
58
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
59
+ vfp_reg_offset(1, rn),
60
+ vfp_reg_offset(1, rm), cpu_env,
61
+ opr_sz, opr_sz, 0, fn);
62
+ return 0;
63
+ }
64
+ return 1;
65
+}
66
+
39
+
67
/* Translate a NEON data processing instruction. Return nonzero if the
40
+ image_url = ('https://dl.armbian.com/orangepipc/archive/'
68
instruction is invalid.
41
+ 'Armbian_20.08.1_Orangepipc_bionic_current_5.8.5.img.xz')
69
We process data in a mixture of 32-bit and 64-bit chunks.
42
+ image_hash = ('b4d6775f5673486329e45a0586bf06b6'
70
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
43
+ 'dbe792199fd182ac6b9c7bb6c7d3e6dd')
71
if (q && ((rd | rn | rm) & 1)) {
44
+ image_path_xz = self.fetch_asset(image_url, asset_hash=image_hash,
72
return 1;
45
+ algorithm='sha256')
73
}
46
+ image_path = archive.extract(image_path_xz, self.workdir)
74
- /*
47
+ image_pow2ceil_expand(image_path)
75
- * The SHA-1/SHA-256 3-register instructions require special treatment
76
- * here, as their size field is overloaded as an op type selector, and
77
- * they all consume their input in a single pass.
78
- */
79
- if (op == NEON_3R_SHA) {
80
+ switch (op) {
81
+ case NEON_3R_SHA:
82
+ /* The SHA-1/SHA-256 3-register instructions require special
83
+ * treatment here, as their size field is overloaded as an
84
+ * op type selector, and they all consume their input in a
85
+ * single pass.
86
+ */
87
if (!q) {
88
return 1;
89
}
90
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
91
tcg_temp_free_ptr(ptr2);
92
tcg_temp_free_ptr(ptr3);
93
return 0;
94
+
48
+
95
+ case NEON_3R_VPADD_VQRDMLAH:
49
self.vm.set_console()
96
+ if (!u) {
50
self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw',
97
+ break; /* VPADD */
51
'-nic', 'user',
98
+ }
52
@@ -XXX,XX +XXX,XX @@ def do_test_arm_orangepi_uboot_armbian(self, image_path):
99
+ /* VQRDMLAH */
53
'to <orangepipc>')
100
+ switch (size) {
54
self.wait_for_console_pattern('Starting Load Kernel Modules...')
101
+ case 1:
55
102
+ return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
56
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
103
+ q, rd, rn, rm);
57
- 'Test artifacts fetched from unreliable apt.armbian.com')
104
+ case 2:
58
- @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
105
+ return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
59
- @skipUnless(P7ZIP_AVAILABLE, '7z not installed')
106
+ q, rd, rn, rm);
60
- def test_arm_orangepi_bionic_19_11(self):
107
+ }
61
- """
108
+ return 1;
62
- :avocado: tags=arch:arm
109
+
63
- :avocado: tags=machine:orangepi-pc
110
+ case NEON_3R_VFM_VQRDMLSH:
64
- :avocado: tags=device:sd
111
+ if (!u) {
65
- """
112
+ /* VFM, VFMS */
66
-
113
+ if (size == 1) {
67
- # This test download a 196MB compressed image and expand it to 1GB
114
+ return 1;
68
- image_url = ('https://dl.armbian.com/orangepipc/archive/'
115
+ }
69
- 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.7z')
116
+ break;
70
- image_hash = '196a8ffb72b0123d92cea4a070894813d305c71e'
117
+ }
71
- image_path_7z = self.fetch_asset(image_url, asset_hash=image_hash)
118
+ /* VQRDMLSH */
72
- image_name = 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.img'
119
+ switch (size) {
73
- image_path = os.path.join(self.workdir, image_name)
120
+ case 1:
74
- process.run("7z e -o%s %s" % (self.workdir, image_path_7z))
121
+ return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
75
- image_pow2ceil_expand(image_path)
122
+ q, rd, rn, rm);
76
-
123
+ case 2:
77
- self.do_test_arm_orangepi_uboot_armbian(image_path)
124
+ return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
78
-
125
+ q, rd, rn, rm);
79
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
126
+ }
80
- 'Test artifacts fetched from unreliable apt.armbian.com')
127
+ return 1;
81
- @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
128
}
82
- def test_arm_orangepi_bionic_20_08(self):
129
if (size == 3 && op != NEON_3R_LOGIC) {
83
- """
130
/* 64-bit element instructions. */
84
- :avocado: tags=arch:arm
131
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
85
- :avocado: tags=machine:orangepi-pc
132
rm = rtmp;
86
- :avocado: tags=device:sd
133
}
87
- """
134
break;
88
-
135
- case NEON_3R_VPADD:
89
- # This test download a 275 MiB compressed image and expand it
136
- if (u) {
90
- # to 1036 MiB, but the underlying filesystem is 1552 MiB...
137
- return 1;
91
- # As we expand it to 2 GiB we are safe.
138
- }
92
-
139
- /* Fall through */
93
- image_url = ('https://dl.armbian.com/orangepipc/archive/'
140
+ case NEON_3R_VPADD_VQRDMLAH:
94
- 'Armbian_20.08.1_Orangepipc_bionic_current_5.8.5.img.xz')
141
case NEON_3R_VPMAX:
95
- image_hash = ('b4d6775f5673486329e45a0586bf06b6'
142
case NEON_3R_VPMIN:
96
- 'dbe792199fd182ac6b9c7bb6c7d3e6dd')
143
pairwise = 1;
97
- image_path_xz = self.fetch_asset(image_url, asset_hash=image_hash,
144
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
98
- algorithm='sha256')
145
return 1;
99
- image_path = archive.extract(image_path_xz, self.workdir)
146
}
100
- image_pow2ceil_expand(image_path)
147
break;
101
-
148
- case NEON_3R_VFM:
102
- self.do_test_arm_orangepi_uboot_armbian(image_path)
149
- if (!arm_dc_feature(s, ARM_FEATURE_VFP4) || u) {
103
-
150
+ case NEON_3R_VFM_VQRDMLSH:
104
@skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
151
+ if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
105
def test_arm_orangepi_uboot_netbsd9(self):
152
return 1;
106
"""
153
}
154
break;
155
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
156
}
157
}
158
break;
159
- case NEON_3R_VPADD:
160
+ case NEON_3R_VPADD_VQRDMLAH:
161
switch (size) {
162
case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
163
case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
164
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
165
}
166
}
167
break;
168
- case NEON_3R_VFM:
169
+ case NEON_3R_VFM_VQRDMLSH:
170
{
171
/* VFMA, VFMS: fused multiply-add */
172
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
173
--
107
--
174
2.16.2
108
2.20.1
175
109
176
110
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Not enabled anywhere yet.
3
Update the download URL of the Armbian 20.08 Bionic image for
4
test_arm_orangepi_bionic_20_08 of the orangepi-pc machine.
4
5
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
The archive.armbian.com URL contains more images and should keep stable
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
for a longer period of time than dl.armbian.com.
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
8
Message-id: 20180228193125.20577-2-richard.henderson@linaro.org
9
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
13
Message-id: 20210310195820.21950-4-nieklinnenbank@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
15
---
11
target/arm/cpu.h | 1 +
16
tests/acceptance/boot_linux_console.py | 2 +-
12
linux-user/elfload.c | 1 +
17
1 file changed, 1 insertion(+), 1 deletion(-)
13
2 files changed, 2 insertions(+)
14
18
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
16
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
21
--- a/tests/acceptance/boot_linux_console.py
18
+++ b/target/arm/cpu.h
22
+++ b/tests/acceptance/boot_linux_console.py
19
@@ -XXX,XX +XXX,XX @@ enum arm_features {
23
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_bionic_20_08(self):
20
ARM_FEATURE_V8_SHA3, /* implements SHA3 part of v8 Crypto Extensions */
24
# to 1036 MiB, but the underlying filesystem is 1552 MiB...
21
ARM_FEATURE_V8_SM3, /* implements SM3 part of v8 Crypto Extensions */
25
# As we expand it to 2 GiB we are safe.
22
ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
26
23
+ ARM_FEATURE_V8_RDM, /* implements v8.1 simd round multiply */
27
- image_url = ('https://dl.armbian.com/orangepipc/archive/'
24
ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
28
+ image_url = ('https://archive.armbian.com/orangepipc/archive/'
25
};
29
'Armbian_20.08.1_Orangepipc_bionic_current_5.8.5.img.xz')
26
30
image_hash = ('b4d6775f5673486329e45a0586bf06b6'
27
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
31
'dbe792199fd182ac6b9c7bb6c7d3e6dd')
28
index XXXXXXX..XXXXXXX 100644
29
--- a/linux-user/elfload.c
30
+++ b/linux-user/elfload.c
31
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
32
GET_FEATURE(ARM_FEATURE_V8_SHA512, ARM_HWCAP_A64_SHA512);
33
GET_FEATURE(ARM_FEATURE_V8_FP16,
34
ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
35
+ GET_FEATURE(ARM_FEATURE_V8_RDM, ARM_HWCAP_A64_ASIMDRDM);
36
#undef GET_FEATURE
37
38
return hwcaps;
39
--
32
--
40
2.16.2
33
2.20.1
41
34
42
35
diff view generated by jsdifflib
1
Define a new board model for the MPS2 with an AN505 FPGA image
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
containing a Cortex-M33. Since the FPGA images for TrustZone
3
cores (AN505, and the similar AN519 for Cortex-M23) have a
4
significantly different layout of devices to the non-TrustZone
5
images, we use a new source file rather than shoehorning them
6
into the existing mps2.c.
7
2
3
The linux kernel 4.20.7 binary for sunxi has been removed from apt.armbian.com:
4
5
$ ARMBIAN_ARTIFACTS_CACHED=yes AVOCADO_ALLOW_LARGE_STORAGE=yes avocado --show=app,console run -t machine:orangepi-pc tests/acceptance/boot_linux_console.py
6
Fetching asset from tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi
7
...
8
(1/6) tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi:
9
CANCEL: Missing asset https://apt.armbian.com/pool/main/l/linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb (0.55 s)
10
11
This commit updates the sunxi kernel to 5.10.16 for the acceptance
12
tests of the orangepi-pc and cubieboard machines.
13
14
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
15
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
16
Message-id: 20210310195820.21950-5-nieklinnenbank@gmail.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180220180325.29818-20-peter.maydell@linaro.org
11
---
18
---
12
hw/arm/Makefile.objs | 1 +
19
tests/acceptance/boot_linux_console.py | 40 +++++++++++++-------------
13
hw/arm/mps2-tz.c | 503 +++++++++++++++++++++++++++++++++++++++++++++++++++
20
tests/acceptance/replay_kernel.py | 8 +++---
14
2 files changed, 504 insertions(+)
21
2 files changed, 24 insertions(+), 24 deletions(-)
15
create mode 100644 hw/arm/mps2-tz.c
16
22
17
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
23
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
18
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/Makefile.objs
25
--- a/tests/acceptance/boot_linux_console.py
20
+++ b/hw/arm/Makefile.objs
26
+++ b/tests/acceptance/boot_linux_console.py
21
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
27
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_initrd(self):
22
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
28
:avocado: tags=machine:cubieboard
23
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
29
"""
24
obj-$(CONFIG_MPS2) += mps2.o
30
deb_url = ('https://apt.armbian.com/pool/main/l/'
25
+obj-$(CONFIG_MPS2) += mps2-tz.o
31
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
26
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
32
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
27
obj-$(CONFIG_IOTKIT) += iotkit.o
33
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
28
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
34
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
29
new file mode 100644
35
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
30
index XXXXXXX..XXXXXXX
36
kernel_path = self.extract_from_deb(deb_path,
31
--- /dev/null
37
- '/boot/vmlinuz-4.20.7-sunxi')
32
+++ b/hw/arm/mps2-tz.c
38
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb'
33
@@ -XXX,XX +XXX,XX @@
39
+ '/boot/vmlinuz-5.10.16-sunxi')
34
+/*
40
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
35
+ * ARM V2M MPS2 board emulation, trustzone aware FPGA images
41
dtb_path = self.extract_from_deb(deb_path, dtb_path)
36
+ *
42
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
37
+ * Copyright (c) 2017 Linaro Limited
43
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
38
+ * Written by Peter Maydell
44
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_sata(self):
39
+ *
45
:avocado: tags=machine:cubieboard
40
+ * This program is free software; you can redistribute it and/or modify
46
"""
41
+ * it under the terms of the GNU General Public License version 2 or
47
deb_url = ('https://apt.armbian.com/pool/main/l/'
42
+ * (at your option) any later version.
48
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
43
+ */
49
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
44
+
50
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
45
+/* The MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
51
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
46
+ * FPGA but is otherwise the same as the 2). Since the CPU itself
52
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
47
+ * and most of the devices are in the FPGA, the details of the board
53
kernel_path = self.extract_from_deb(deb_path,
48
+ * as seen by the guest depend significantly on the FPGA image.
54
- '/boot/vmlinuz-4.20.7-sunxi')
49
+ * This source file covers the following FPGA images, for TrustZone cores:
55
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb'
50
+ * "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
56
+ '/boot/vmlinuz-5.10.16-sunxi')
51
+ *
57
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
52
+ * Links to the TRM for the board itself and to the various Application
58
dtb_path = self.extract_from_deb(deb_path, dtb_path)
53
+ * Notes which document the FPGA images can be found here:
59
rootfs_url = ('https://github.com/groeck/linux-build-test/raw/'
54
+ * https://developer.arm.com/products/system-design/development-boards/fpga-prototyping-boards/mps2
60
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
55
+ *
61
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi(self):
56
+ * Board TRM:
62
:avocado: tags=machine:orangepi-pc
57
+ * http://infocenter.arm.com/help/topic/com.arm.doc.100112_0200_06_en/versatile_express_cortex_m_prototyping_systems_v2m_mps2_and_v2m_mps2plus_technical_reference_100112_0200_06_en.pdf
63
"""
58
+ * Application Note AN505:
64
deb_url = ('https://apt.armbian.com/pool/main/l/'
59
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
65
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
60
+ *
66
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
61
+ * The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
67
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
62
+ * (ARM ECM0601256) for the details of some of the device layout:
68
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
63
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
69
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
64
+ */
70
kernel_path = self.extract_from_deb(deb_path,
65
+
71
- '/boot/vmlinuz-4.20.7-sunxi')
66
+#include "qemu/osdep.h"
72
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
67
+#include "qapi/error.h"
73
+ '/boot/vmlinuz-5.10.16-sunxi')
68
+#include "qemu/error-report.h"
74
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
69
+#include "hw/arm/arm.h"
75
dtb_path = self.extract_from_deb(deb_path, dtb_path)
70
+#include "hw/arm/armv7m.h"
76
71
+#include "hw/or-irq.h"
77
self.vm.set_console()
72
+#include "hw/boards.h"
78
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_initrd(self):
73
+#include "exec/address-spaces.h"
79
:avocado: tags=machine:orangepi-pc
74
+#include "sysemu/sysemu.h"
80
"""
75
+#include "hw/misc/unimp.h"
81
deb_url = ('https://apt.armbian.com/pool/main/l/'
76
+#include "hw/char/cmsdk-apb-uart.h"
82
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
77
+#include "hw/timer/cmsdk-apb-timer.h"
83
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
78
+#include "hw/misc/mps2-scc.h"
84
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
79
+#include "hw/misc/mps2-fpgaio.h"
85
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
80
+#include "hw/arm/iotkit.h"
86
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
81
+#include "hw/devices.h"
87
kernel_path = self.extract_from_deb(deb_path,
82
+#include "net/net.h"
88
- '/boot/vmlinuz-4.20.7-sunxi')
83
+#include "hw/core/split-irq.h"
89
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
84
+
90
+ '/boot/vmlinuz-5.10.16-sunxi')
85
+typedef enum MPS2TZFPGAType {
91
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
86
+ FPGA_AN505,
92
dtb_path = self.extract_from_deb(deb_path, dtb_path)
87
+} MPS2TZFPGAType;
93
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
88
+
94
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
89
+typedef struct {
95
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_sd(self):
90
+ MachineClass parent;
96
:avocado: tags=device:sd
91
+ MPS2TZFPGAType fpga_type;
97
"""
92
+ uint32_t scc_id;
98
deb_url = ('https://apt.armbian.com/pool/main/l/'
93
+} MPS2TZMachineClass;
99
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
94
+
100
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
95
+typedef struct {
101
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
96
+ MachineState parent;
102
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
97
+
103
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
98
+ IoTKit iotkit;
104
kernel_path = self.extract_from_deb(deb_path,
99
+ MemoryRegion psram;
105
- '/boot/vmlinuz-4.20.7-sunxi')
100
+ MemoryRegion ssram1;
106
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
101
+ MemoryRegion ssram1_m;
107
+ '/boot/vmlinuz-5.10.16-sunxi')
102
+ MemoryRegion ssram23;
108
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
103
+ MPS2SCC scc;
109
dtb_path = self.extract_from_deb(deb_path, dtb_path)
104
+ MPS2FPGAIO fpgaio;
110
rootfs_url = ('http://storage.kernelci.org/images/rootfs/buildroot/'
105
+ TZPPC ppc[5];
111
'kci-2019.02/armel/base/rootfs.ext2.xz')
106
+ UnimplementedDeviceState ssram_mpc[3];
112
diff --git a/tests/acceptance/replay_kernel.py b/tests/acceptance/replay_kernel.py
107
+ UnimplementedDeviceState spi[5];
113
index XXXXXXX..XXXXXXX 100644
108
+ UnimplementedDeviceState i2c[4];
114
--- a/tests/acceptance/replay_kernel.py
109
+ UnimplementedDeviceState i2s_audio;
115
+++ b/tests/acceptance/replay_kernel.py
110
+ UnimplementedDeviceState gpio[5];
116
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_initrd(self):
111
+ UnimplementedDeviceState dma[4];
117
:avocado: tags=machine:cubieboard
112
+ UnimplementedDeviceState gfx;
118
"""
113
+ CMSDKAPBUART uart[5];
119
deb_url = ('https://apt.armbian.com/pool/main/l/'
114
+ SplitIRQ sec_resp_splitter;
120
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
115
+ qemu_or_irq uart_irq_orgate;
121
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
116
+} MPS2TZMachineState;
122
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
117
+
123
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
118
+#define TYPE_MPS2TZ_MACHINE "mps2tz"
124
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
119
+#define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
125
kernel_path = self.extract_from_deb(deb_path,
120
+
126
- '/boot/vmlinuz-4.20.7-sunxi')
121
+#define MPS2TZ_MACHINE(obj) \
127
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb'
122
+ OBJECT_CHECK(MPS2TZMachineState, obj, TYPE_MPS2TZ_MACHINE)
128
+ '/boot/vmlinuz-5.10.16-sunxi')
123
+#define MPS2TZ_MACHINE_GET_CLASS(obj) \
129
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
124
+ OBJECT_GET_CLASS(MPS2TZMachineClass, obj, TYPE_MPS2TZ_MACHINE)
130
dtb_path = self.extract_from_deb(deb_path, dtb_path)
125
+#define MPS2TZ_MACHINE_CLASS(klass) \
131
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
126
+ OBJECT_CLASS_CHECK(MPS2TZMachineClass, klass, TYPE_MPS2TZ_MACHINE)
132
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
127
+
128
+/* Main SYSCLK frequency in Hz */
129
+#define SYSCLK_FRQ 20000000
130
+
131
+/* Initialize the auxiliary RAM region @mr and map it into
132
+ * the memory map at @base.
133
+ */
134
+static void make_ram(MemoryRegion *mr, const char *name,
135
+ hwaddr base, hwaddr size)
136
+{
137
+ memory_region_init_ram(mr, NULL, name, size, &error_fatal);
138
+ memory_region_add_subregion(get_system_memory(), base, mr);
139
+}
140
+
141
+/* Create an alias of an entire original MemoryRegion @orig
142
+ * located at @base in the memory map.
143
+ */
144
+static void make_ram_alias(MemoryRegion *mr, const char *name,
145
+ MemoryRegion *orig, hwaddr base)
146
+{
147
+ memory_region_init_alias(mr, NULL, name, orig, 0,
148
+ memory_region_size(orig));
149
+ memory_region_add_subregion(get_system_memory(), base, mr);
150
+}
151
+
152
+static void init_sysbus_child(Object *parent, const char *childname,
153
+ void *child, size_t childsize,
154
+ const char *childtype)
155
+{
156
+ object_initialize(child, childsize, childtype);
157
+ object_property_add_child(parent, childname, OBJECT(child), &error_abort);
158
+ qdev_set_parent_bus(DEVICE(child), sysbus_get_default());
159
+
160
+}
161
+
162
+/* Most of the devices in the AN505 FPGA image sit behind
163
+ * Peripheral Protection Controllers. These data structures
164
+ * define the layout of which devices sit behind which PPCs.
165
+ * The devfn for each port is a function which creates, configures
166
+ * and initializes the device, returning the MemoryRegion which
167
+ * needs to be plugged into the downstream end of the PPC port.
168
+ */
169
+typedef MemoryRegion *MakeDevFn(MPS2TZMachineState *mms, void *opaque,
170
+ const char *name, hwaddr size);
171
+
172
+typedef struct PPCPortInfo {
173
+ const char *name;
174
+ MakeDevFn *devfn;
175
+ void *opaque;
176
+ hwaddr addr;
177
+ hwaddr size;
178
+} PPCPortInfo;
179
+
180
+typedef struct PPCInfo {
181
+ const char *name;
182
+ PPCPortInfo ports[TZ_NUM_PORTS];
183
+} PPCInfo;
184
+
185
+static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
186
+ void *opaque,
187
+ const char *name, hwaddr size)
188
+{
189
+ /* Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
190
+ * and return a pointer to its MemoryRegion.
191
+ */
192
+ UnimplementedDeviceState *uds = opaque;
193
+
194
+ init_sysbus_child(OBJECT(mms), name, uds,
195
+ sizeof(UnimplementedDeviceState),
196
+ TYPE_UNIMPLEMENTED_DEVICE);
197
+ qdev_prop_set_string(DEVICE(uds), "name", name);
198
+ qdev_prop_set_uint64(DEVICE(uds), "size", size);
199
+ object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
200
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
201
+}
202
+
203
+static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
204
+ const char *name, hwaddr size)
205
+{
206
+ CMSDKAPBUART *uart = opaque;
207
+ int i = uart - &mms->uart[0];
208
+ Chardev *uartchr = i < MAX_SERIAL_PORTS ? serial_hds[i] : NULL;
209
+ int rxirqno = i * 2;
210
+ int txirqno = i * 2 + 1;
211
+ int combirqno = i + 10;
212
+ SysBusDevice *s;
213
+ DeviceState *iotkitdev = DEVICE(&mms->iotkit);
214
+ DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
215
+
216
+ init_sysbus_child(OBJECT(mms), name, uart,
217
+ sizeof(mms->uart[0]), TYPE_CMSDK_APB_UART);
218
+ qdev_prop_set_chr(DEVICE(uart), "chardev", uartchr);
219
+ qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ);
220
+ object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal);
221
+ s = SYS_BUS_DEVICE(uart);
222
+ sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev,
223
+ "EXP_IRQ", txirqno));
224
+ sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev,
225
+ "EXP_IRQ", rxirqno));
226
+ sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2));
227
+ sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1));
228
+ sysbus_connect_irq(s, 4, qdev_get_gpio_in_named(iotkitdev,
229
+ "EXP_IRQ", combirqno));
230
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
231
+}
232
+
233
+static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
234
+ const char *name, hwaddr size)
235
+{
236
+ MPS2SCC *scc = opaque;
237
+ DeviceState *sccdev;
238
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
239
+
240
+ object_initialize(scc, sizeof(mms->scc), TYPE_MPS2_SCC);
241
+ sccdev = DEVICE(scc);
242
+ qdev_set_parent_bus(sccdev, sysbus_get_default());
243
+ qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
244
+ qdev_prop_set_uint32(sccdev, "scc-aid", 0x02000008);
245
+ qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
246
+ object_property_set_bool(OBJECT(scc), true, "realized", &error_fatal);
247
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
248
+}
249
+
250
+static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
251
+ const char *name, hwaddr size)
252
+{
253
+ MPS2FPGAIO *fpgaio = opaque;
254
+
255
+ object_initialize(fpgaio, sizeof(mms->fpgaio), TYPE_MPS2_FPGAIO);
256
+ qdev_set_parent_bus(DEVICE(fpgaio), sysbus_get_default());
257
+ object_property_set_bool(OBJECT(fpgaio), true, "realized", &error_fatal);
258
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
259
+}
260
+
261
+static void mps2tz_common_init(MachineState *machine)
262
+{
263
+ MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
264
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
265
+ MemoryRegion *system_memory = get_system_memory();
266
+ DeviceState *iotkitdev;
267
+ DeviceState *dev_splitter;
268
+ int i;
269
+
270
+ if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
271
+ error_report("This board can only be used with CPU %s",
272
+ mc->default_cpu_type);
273
+ exit(1);
274
+ }
275
+
276
+ init_sysbus_child(OBJECT(machine), "iotkit", &mms->iotkit,
277
+ sizeof(mms->iotkit), TYPE_IOTKIT);
278
+ iotkitdev = DEVICE(&mms->iotkit);
279
+ object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory),
280
+ "memory", &error_abort);
281
+ qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", 92);
282
+ qdev_prop_set_uint32(iotkitdev, "MAINCLK", SYSCLK_FRQ);
283
+ object_property_set_bool(OBJECT(&mms->iotkit), true, "realized",
284
+ &error_fatal);
285
+
286
+ /* The sec_resp_cfg output from the IoTKit must be split into multiple
287
+ * lines, one for each of the PPCs we create here.
288
+ */
289
+ object_initialize(&mms->sec_resp_splitter, sizeof(mms->sec_resp_splitter),
290
+ TYPE_SPLIT_IRQ);
291
+ object_property_add_child(OBJECT(machine), "sec-resp-splitter",
292
+ OBJECT(&mms->sec_resp_splitter), &error_abort);
293
+ object_property_set_int(OBJECT(&mms->sec_resp_splitter), 5,
294
+ "num-lines", &error_fatal);
295
+ object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true,
296
+ "realized", &error_fatal);
297
+ dev_splitter = DEVICE(&mms->sec_resp_splitter);
298
+ qdev_connect_gpio_out_named(iotkitdev, "sec_resp_cfg", 0,
299
+ qdev_get_gpio_in(dev_splitter, 0));
300
+
301
+ /* The IoTKit sets up much of the memory layout, including
302
+ * the aliases between secure and non-secure regions in the
303
+ * address space. The FPGA itself contains:
304
+ *
305
+ * 0x00000000..0x003fffff SSRAM1
306
+ * 0x00400000..0x007fffff alias of SSRAM1
307
+ * 0x28000000..0x283fffff 4MB SSRAM2 + SSRAM3
308
+ * 0x40100000..0x4fffffff AHB Master Expansion 1 interface devices
309
+ * 0x80000000..0x80ffffff 16MB PSRAM
310
+ */
311
+
312
+ /* The FPGA images have an odd combination of different RAMs,
313
+ * because in hardware they are different implementations and
314
+ * connected to different buses, giving varying performance/size
315
+ * tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
316
+ * call the 16MB our "system memory", as it's the largest lump.
317
+ */
318
+ memory_region_allocate_system_memory(&mms->psram,
319
+ NULL, "mps.ram", 0x01000000);
320
+ memory_region_add_subregion(system_memory, 0x80000000, &mms->psram);
321
+
322
+ /* The SSRAM memories should all be behind Memory Protection Controllers,
323
+ * but we don't implement that yet.
324
+ */
325
+ make_ram(&mms->ssram1, "mps.ssram1", 0x00000000, 0x00400000);
326
+ make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x00400000);
327
+
328
+ make_ram(&mms->ssram23, "mps.ssram23", 0x28000000, 0x00400000);
329
+
330
+ /* The overflow IRQs for all UARTs are ORed together.
331
+ * Tx, Rx and "combined" IRQs are sent to the NVIC separately.
332
+ * Create the OR gate for this.
333
+ */
334
+ object_initialize(&mms->uart_irq_orgate, sizeof(mms->uart_irq_orgate),
335
+ TYPE_OR_IRQ);
336
+ object_property_add_child(OBJECT(mms), "uart-irq-orgate",
337
+ OBJECT(&mms->uart_irq_orgate), &error_abort);
338
+ object_property_set_int(OBJECT(&mms->uart_irq_orgate), 10, "num-lines",
339
+ &error_fatal);
340
+ object_property_set_bool(OBJECT(&mms->uart_irq_orgate), true,
341
+ "realized", &error_fatal);
342
+ qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
343
+ qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 15));
344
+
345
+ /* Most of the devices in the FPGA are behind Peripheral Protection
346
+ * Controllers. The required order for initializing things is:
347
+ * + initialize the PPC
348
+ * + initialize, configure and realize downstream devices
349
+ * + connect downstream device MemoryRegions to the PPC
350
+ * + realize the PPC
351
+ * + map the PPC's MemoryRegions to the places in the address map
352
+ * where the downstream devices should appear
353
+ * + wire up the PPC's control lines to the IoTKit object
354
+ */
355
+
356
+ const PPCInfo ppcs[] = { {
357
+ .name = "apb_ppcexp0",
358
+ .ports = {
359
+ { "ssram-mpc0", make_unimp_dev, &mms->ssram_mpc[0],
360
+ 0x58007000, 0x1000 },
361
+ { "ssram-mpc1", make_unimp_dev, &mms->ssram_mpc[1],
362
+ 0x58008000, 0x1000 },
363
+ { "ssram-mpc2", make_unimp_dev, &mms->ssram_mpc[2],
364
+ 0x58009000, 0x1000 },
365
+ },
366
+ }, {
367
+ .name = "apb_ppcexp1",
368
+ .ports = {
369
+ { "spi0", make_unimp_dev, &mms->spi[0], 0x40205000, 0x1000 },
370
+ { "spi1", make_unimp_dev, &mms->spi[1], 0x40206000, 0x1000 },
371
+ { "spi2", make_unimp_dev, &mms->spi[2], 0x40209000, 0x1000 },
372
+ { "spi3", make_unimp_dev, &mms->spi[3], 0x4020a000, 0x1000 },
373
+ { "spi4", make_unimp_dev, &mms->spi[4], 0x4020b000, 0x1000 },
374
+ { "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000 },
375
+ { "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000 },
376
+ { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000 },
377
+ { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000 },
378
+ { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000 },
379
+ { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40207000, 0x1000 },
380
+ { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40208000, 0x1000 },
381
+ { "i2c2", make_unimp_dev, &mms->i2c[2], 0x4020c000, 0x1000 },
382
+ { "i2c3", make_unimp_dev, &mms->i2c[3], 0x4020d000, 0x1000 },
383
+ },
384
+ }, {
385
+ .name = "apb_ppcexp2",
386
+ .ports = {
387
+ { "scc", make_scc, &mms->scc, 0x40300000, 0x1000 },
388
+ { "i2s-audio", make_unimp_dev, &mms->i2s_audio,
389
+ 0x40301000, 0x1000 },
390
+ { "fpgaio", make_fpgaio, &mms->fpgaio, 0x40302000, 0x1000 },
391
+ },
392
+ }, {
393
+ .name = "ahb_ppcexp0",
394
+ .ports = {
395
+ { "gfx", make_unimp_dev, &mms->gfx, 0x41000000, 0x140000 },
396
+ { "gpio0", make_unimp_dev, &mms->gpio[0], 0x40100000, 0x1000 },
397
+ { "gpio1", make_unimp_dev, &mms->gpio[1], 0x40101000, 0x1000 },
398
+ { "gpio2", make_unimp_dev, &mms->gpio[2], 0x40102000, 0x1000 },
399
+ { "gpio3", make_unimp_dev, &mms->gpio[3], 0x40103000, 0x1000 },
400
+ { "gpio4", make_unimp_dev, &mms->gpio[4], 0x40104000, 0x1000 },
401
+ },
402
+ }, {
403
+ .name = "ahb_ppcexp1",
404
+ .ports = {
405
+ { "dma0", make_unimp_dev, &mms->dma[0], 0x40110000, 0x1000 },
406
+ { "dma1", make_unimp_dev, &mms->dma[1], 0x40111000, 0x1000 },
407
+ { "dma2", make_unimp_dev, &mms->dma[2], 0x40112000, 0x1000 },
408
+ { "dma3", make_unimp_dev, &mms->dma[3], 0x40113000, 0x1000 },
409
+ },
410
+ },
411
+ };
412
+
413
+ for (i = 0; i < ARRAY_SIZE(ppcs); i++) {
414
+ const PPCInfo *ppcinfo = &ppcs[i];
415
+ TZPPC *ppc = &mms->ppc[i];
416
+ DeviceState *ppcdev;
417
+ int port;
418
+ char *gpioname;
419
+
420
+ init_sysbus_child(OBJECT(machine), ppcinfo->name, ppc,
421
+ sizeof(TZPPC), TYPE_TZ_PPC);
422
+ ppcdev = DEVICE(ppc);
423
+
424
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
425
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
426
+ MemoryRegion *mr;
427
+ char *portname;
428
+
429
+ if (!pinfo->devfn) {
430
+ continue;
431
+ }
432
+
433
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
434
+ portname = g_strdup_printf("port[%d]", port);
435
+ object_property_set_link(OBJECT(ppc), OBJECT(mr),
436
+ portname, &error_fatal);
437
+ g_free(portname);
438
+ }
439
+
440
+ object_property_set_bool(OBJECT(ppc), true, "realized", &error_fatal);
441
+
442
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
443
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
444
+
445
+ if (!pinfo->devfn) {
446
+ continue;
447
+ }
448
+ sysbus_mmio_map(SYS_BUS_DEVICE(ppc), port, pinfo->addr);
449
+
450
+ gpioname = g_strdup_printf("%s_nonsec", ppcinfo->name);
451
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, port,
452
+ qdev_get_gpio_in_named(ppcdev,
453
+ "cfg_nonsec",
454
+ port));
455
+ g_free(gpioname);
456
+ gpioname = g_strdup_printf("%s_ap", ppcinfo->name);
457
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, port,
458
+ qdev_get_gpio_in_named(ppcdev,
459
+ "cfg_ap", port));
460
+ g_free(gpioname);
461
+ }
462
+
463
+ gpioname = g_strdup_printf("%s_irq_enable", ppcinfo->name);
464
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, 0,
465
+ qdev_get_gpio_in_named(ppcdev,
466
+ "irq_enable", 0));
467
+ g_free(gpioname);
468
+ gpioname = g_strdup_printf("%s_irq_clear", ppcinfo->name);
469
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, 0,
470
+ qdev_get_gpio_in_named(ppcdev,
471
+ "irq_clear", 0));
472
+ g_free(gpioname);
473
+ gpioname = g_strdup_printf("%s_irq_status", ppcinfo->name);
474
+ qdev_connect_gpio_out_named(ppcdev, "irq", 0,
475
+ qdev_get_gpio_in_named(iotkitdev,
476
+ gpioname, 0));
477
+ g_free(gpioname);
478
+
479
+ qdev_connect_gpio_out(dev_splitter, i,
480
+ qdev_get_gpio_in_named(ppcdev,
481
+ "cfg_sec_resp", 0));
482
+ }
483
+
484
+ /* In hardware this is a LAN9220; the LAN9118 is software compatible
485
+ * except that it doesn't support the checksum-offload feature.
486
+ * The ethernet controller is not behind a PPC.
487
+ */
488
+ lan9118_init(&nd_table[0], 0x42000000,
489
+ qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 16));
490
+
491
+ create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
492
+
493
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
494
+}
495
+
496
+static void mps2tz_class_init(ObjectClass *oc, void *data)
497
+{
498
+ MachineClass *mc = MACHINE_CLASS(oc);
499
+
500
+ mc->init = mps2tz_common_init;
501
+ mc->max_cpus = 1;
502
+}
503
+
504
+static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
505
+{
506
+ MachineClass *mc = MACHINE_CLASS(oc);
507
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
508
+
509
+ mc->desc = "ARM MPS2 with AN505 FPGA image for Cortex-M33";
510
+ mmc->fpga_type = FPGA_AN505;
511
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
512
+ mmc->scc_id = 0x41040000 | (505 << 4);
513
+}
514
+
515
+static const TypeInfo mps2tz_info = {
516
+ .name = TYPE_MPS2TZ_MACHINE,
517
+ .parent = TYPE_MACHINE,
518
+ .abstract = true,
519
+ .instance_size = sizeof(MPS2TZMachineState),
520
+ .class_size = sizeof(MPS2TZMachineClass),
521
+ .class_init = mps2tz_class_init,
522
+};
523
+
524
+static const TypeInfo mps2tz_an505_info = {
525
+ .name = TYPE_MPS2TZ_AN505_MACHINE,
526
+ .parent = TYPE_MPS2TZ_MACHINE,
527
+ .class_init = mps2tz_an505_class_init,
528
+};
529
+
530
+static void mps2tz_machine_init(void)
531
+{
532
+ type_register_static(&mps2tz_info);
533
+ type_register_static(&mps2tz_an505_info);
534
+}
535
+
536
+type_init(mps2tz_machine_init);
537
--
133
--
538
2.16.2
134
2.20.1
539
135
540
136
diff view generated by jsdifflib
1
The function qdev_init_gpio_in_named() passes the DeviceState pointer
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
as the opaque data pointor for the irq handler function. Usually
3
this is what you want, but in some cases it would be helpful to use
4
some other data pointer.
5
2
6
Add a new function qdev_init_gpio_in_named_with_opaque() which allows
3
Previously the ARMBIAN_ARTIFACTS_CACHED pre-condition was added to allow running
7
the caller to specify the data pointer they want.
4
tests that have already existing armbian.com artifacts stored in the local avocado cache,
5
but do not have working URLs to download a fresh copy.
8
6
7
At this time of writing the URLs for artifacts on the armbian.com server are updated and working.
8
Any future broken URLs will result in a skipped acceptance test, for example:
9
10
(1/5) tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi:
11
CANCEL: Missing asset https://apt.armbian.com/pool/main/l/linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb (0.53 s)
12
13
This commits removes the ARMBIAN_ARTIFACTS_CACHED pre-condition such that
14
the acceptance tests for the orangepi-pc and cubieboard machines can run.
15
16
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
17
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
18
Message-id: 20210310195820.21950-6-nieklinnenbank@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20180220180325.29818-12-peter.maydell@linaro.org
13
---
20
---
14
include/hw/qdev-core.h | 30 ++++++++++++++++++++++++++++--
21
tests/acceptance/boot_linux_console.py | 12 ------------
15
hw/core/qdev.c | 8 +++++---
22
tests/acceptance/replay_kernel.py | 2 --
16
2 files changed, 33 insertions(+), 5 deletions(-)
23
2 files changed, 14 deletions(-)
17
24
18
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
25
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
19
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/qdev-core.h
27
--- a/tests/acceptance/boot_linux_console.py
21
+++ b/include/hw/qdev-core.h
28
+++ b/tests/acceptance/boot_linux_console.py
22
@@ -XXX,XX +XXX,XX @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
29
@@ -XXX,XX +XXX,XX @@ def test_arm_exynos4210_initrd(self):
23
/* GPIO inputs also double as IRQ sinks. */
30
self.wait_for_console_pattern('Boot successful.')
24
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
31
# TODO user command, for now the uart is stuck
25
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
32
26
-void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler,
33
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
27
- const char *name, int n);
34
- 'Test artifacts fetched from unreliable apt.armbian.com')
28
void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
35
def test_arm_cubieboard_initrd(self):
29
const char *name, int n);
36
"""
30
+/**
37
:avocado: tags=arch:arm
31
+ * qdev_init_gpio_in_named_with_opaque: create an array of input GPIO lines
38
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_initrd(self):
32
+ * for the specified device
39
'system-control@1c00000')
33
+ *
40
# cubieboard's reboot is not functioning; omit reboot test.
34
+ * @dev: Device to create input GPIOs for
41
35
+ * @handler: Function to call when GPIO line value is set
42
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
36
+ * @opaque: Opaque data pointer to pass to @handler
43
- 'Test artifacts fetched from unreliable apt.armbian.com')
37
+ * @name: Name of the GPIO input (must be unique for this device)
44
def test_arm_cubieboard_sata(self):
38
+ * @n: Number of GPIO lines in this input set
45
"""
39
+ */
46
:avocado: tags=arch:arm
40
+void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
47
@@ -XXX,XX +XXX,XX @@ def test_arm_quanta_gsj_initrd(self):
41
+ qemu_irq_handler handler,
48
self.wait_for_console_pattern(
42
+ void *opaque,
49
'Give root password for system maintenance')
43
+ const char *name, int n);
50
44
+
51
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
45
+/**
52
- 'Test artifacts fetched from unreliable apt.armbian.com')
46
+ * qdev_init_gpio_in_named: create an array of input GPIO lines
53
def test_arm_orangepi(self):
47
+ * for the specified device
54
"""
48
+ *
55
:avocado: tags=arch:arm
49
+ * Like qdev_init_gpio_in_named_with_opaque(), but the opaque pointer
56
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi(self):
50
+ * passed to the handler is @dev (which is the most commonly desired behaviour).
57
console_pattern = 'Kernel command line: %s' % kernel_command_line
51
+ */
58
self.wait_for_console_pattern(console_pattern)
52
+static inline void qdev_init_gpio_in_named(DeviceState *dev,
59
53
+ qemu_irq_handler handler,
60
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
54
+ const char *name, int n)
61
- 'Test artifacts fetched from unreliable apt.armbian.com')
55
+{
62
def test_arm_orangepi_initrd(self):
56
+ qdev_init_gpio_in_named_with_opaque(dev, handler, dev, name, n);
63
"""
57
+}
64
:avocado: tags=arch:arm
58
65
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_initrd(self):
59
void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
66
# Wait for VM to shut down gracefully
60
const char *name);
67
self.vm.wait()
61
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
68
69
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
70
- 'Test artifacts fetched from unreliable apt.armbian.com')
71
def test_arm_orangepi_sd(self):
72
"""
73
:avocado: tags=arch:arm
74
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_sd(self):
75
# Wait for VM to shut down gracefully
76
self.vm.wait()
77
78
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
79
- 'Test artifacts fetched from unreliable apt.armbian.com')
80
@skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
81
def test_arm_orangepi_bionic_20_08(self):
82
"""
83
diff --git a/tests/acceptance/replay_kernel.py b/tests/acceptance/replay_kernel.py
62
index XXXXXXX..XXXXXXX 100644
84
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/core/qdev.c
85
--- a/tests/acceptance/replay_kernel.py
64
+++ b/hw/core/qdev.c
86
+++ b/tests/acceptance/replay_kernel.py
65
@@ -XXX,XX +XXX,XX @@ static NamedGPIOList *qdev_get_named_gpio_list(DeviceState *dev,
87
@@ -XXX,XX +XXX,XX @@ def test_arm_virt(self):
66
return ngl;
88
self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1)
67
}
89
68
90
@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab')
69
-void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler,
91
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
70
- const char *name, int n)
92
- 'Test artifacts fetched from unreliable apt.armbian.com')
71
+void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
93
def test_arm_cubieboard_initrd(self):
72
+ qemu_irq_handler handler,
94
"""
73
+ void *opaque,
95
:avocado: tags=arch:arm
74
+ const char *name, int n)
75
{
76
int i;
77
NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
78
79
assert(gpio_list->num_out == 0 || !name);
80
gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler,
81
- dev, n);
82
+ opaque, n);
83
84
if (!name) {
85
name = "unnamed-gpio-in";
86
--
96
--
87
2.16.2
97
2.20.1
88
98
89
99
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
If the SSECounter link is absent, we set an error message
4
Message-id: 20180228193125.20577-13-richard.henderson@linaro.org
4
in sse_timer_realize() but forgot to propagate this error.
5
Add the missing 'return'.
6
7
Fixes: CID 1450755 (Null pointer dereferences)
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210312001845.1562670-1-f4bug@amsat.org
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
[PMM: renamed e1/e2/e3/e4 to use the same naming as the version
7
of the pseudocode in the Arm ARM]
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
---
12
---
10
target/arm/helper.h | 11 ++++
13
hw/timer/sse-timer.c | 1 +
11
target/arm/translate-a64.c | 94 +++++++++++++++++++++++++---
14
1 file changed, 1 insertion(+)
12
target/arm/vec_helper.c | 149 +++++++++++++++++++++++++++++++++++++++++++++
13
3 files changed, 246 insertions(+), 8 deletions(-)
14
15
15
diff --git a/target/arm/helper.h b/target/arm/helper.h
16
diff --git a/hw/timer/sse-timer.c b/hw/timer/sse-timer.c
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.h
18
--- a/hw/timer/sse-timer.c
18
+++ b/target/arm/helper.h
19
+++ b/hw/timer/sse-timer.c
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fcadds, TCG_CALL_NO_RWG,
20
@@ -XXX,XX +XXX,XX @@ static void sse_timer_realize(DeviceState *dev, Error **errp)
20
DEF_HELPER_FLAGS_5(gvec_fcaddd, TCG_CALL_NO_RWG,
21
21
void, ptr, ptr, ptr, ptr, i32)
22
if (!s->counter) {
22
23
error_setg(errp, "counter property was not set");
23
+DEF_HELPER_FLAGS_5(gvec_fcmlah, TCG_CALL_NO_RWG,
24
+ void, ptr, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_5(gvec_fcmlah_idx, TCG_CALL_NO_RWG,
26
+ void, ptr, ptr, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_5(gvec_fcmlas, TCG_CALL_NO_RWG,
28
+ void, ptr, ptr, ptr, ptr, i32)
29
+DEF_HELPER_FLAGS_5(gvec_fcmlas_idx, TCG_CALL_NO_RWG,
30
+ void, ptr, ptr, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_5(gvec_fcmlad, TCG_CALL_NO_RWG,
32
+ void, ptr, ptr, ptr, ptr, i32)
33
+
34
#ifdef TARGET_AARCH64
35
#include "helper-a64.h"
36
#endif
37
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate-a64.c
40
+++ b/target/arm/translate-a64.c
41
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
42
}
43
feature = ARM_FEATURE_V8_RDM;
44
break;
45
+ case 0x8: /* FCMLA, #0 */
46
+ case 0x9: /* FCMLA, #90 */
47
+ case 0xa: /* FCMLA, #180 */
48
+ case 0xb: /* FCMLA, #270 */
49
case 0xc: /* FCADD, #90 */
50
case 0xe: /* FCADD, #270 */
51
if (size == 0
52
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
53
}
54
return;
55
56
+ case 0x8: /* FCMLA, #0 */
57
+ case 0x9: /* FCMLA, #90 */
58
+ case 0xa: /* FCMLA, #180 */
59
+ case 0xb: /* FCMLA, #270 */
60
+ rot = extract32(opcode, 0, 2);
61
+ switch (size) {
62
+ case 1:
63
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, true, rot,
64
+ gen_helper_gvec_fcmlah);
65
+ break;
66
+ case 2:
67
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
68
+ gen_helper_gvec_fcmlas);
69
+ break;
70
+ case 3:
71
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
72
+ gen_helper_gvec_fcmlad);
73
+ break;
74
+ default:
75
+ g_assert_not_reached();
76
+ }
77
+ return;
78
+
79
case 0xc: /* FCADD, #90 */
80
case 0xe: /* FCADD, #270 */
81
rot = extract32(opcode, 1, 1);
82
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
83
int rn = extract32(insn, 5, 5);
84
int rd = extract32(insn, 0, 5);
85
bool is_long = false;
86
- bool is_fp = false;
87
+ int is_fp = 0;
88
bool is_fp16 = false;
89
int index;
90
TCGv_ptr fpst;
91
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
92
case 0x05: /* FMLS */
93
case 0x09: /* FMUL */
94
case 0x19: /* FMULX */
95
- is_fp = true;
96
+ is_fp = 1;
97
break;
98
case 0x1d: /* SQRDMLAH */
99
case 0x1f: /* SQRDMLSH */
100
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
101
return;
102
}
103
break;
104
+ case 0x11: /* FCMLA #0 */
105
+ case 0x13: /* FCMLA #90 */
106
+ case 0x15: /* FCMLA #180 */
107
+ case 0x17: /* FCMLA #270 */
108
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)) {
109
+ unallocated_encoding(s);
110
+ return;
111
+ }
112
+ is_fp = 2;
113
+ break;
114
default:
115
unallocated_encoding(s);
116
return;
117
}
118
119
- if (is_fp) {
120
+ switch (is_fp) {
121
+ case 1: /* normal fp */
122
/* convert insn encoded size to TCGMemOp size */
123
switch (size) {
124
case 0: /* half-precision */
125
- if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
126
- unallocated_encoding(s);
127
- return;
128
- }
129
size = MO_16;
130
+ is_fp16 = true;
131
break;
132
case MO_32: /* single precision */
133
case MO_64: /* double precision */
134
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
135
unallocated_encoding(s);
136
return;
137
}
138
- } else {
139
+ break;
140
+
141
+ case 2: /* complex fp */
142
+ /* Each indexable element is a complex pair. */
143
+ size <<= 1;
144
+ switch (size) {
145
+ case MO_32:
146
+ if (h && !is_q) {
147
+ unallocated_encoding(s);
148
+ return;
149
+ }
150
+ is_fp16 = true;
151
+ break;
152
+ case MO_64:
153
+ break;
154
+ default:
155
+ unallocated_encoding(s);
156
+ return;
157
+ }
158
+ break;
159
+
160
+ default: /* integer */
161
switch (size) {
162
case MO_8:
163
case MO_64:
164
unallocated_encoding(s);
165
return;
166
}
167
+ break;
168
+ }
169
+ if (is_fp16 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
170
+ unallocated_encoding(s);
171
+ return;
24
+ return;
172
}
25
}
173
26
174
/* Given TCGMemOp size, adjust register and indexing. */
27
s->counter_notifier.notify = sse_timer_counter_callback;
175
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
176
fpst = NULL;
177
}
178
179
+ switch (16 * u + opcode) {
180
+ case 0x11: /* FCMLA #0 */
181
+ case 0x13: /* FCMLA #90 */
182
+ case 0x15: /* FCMLA #180 */
183
+ case 0x17: /* FCMLA #270 */
184
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
185
+ vec_full_reg_offset(s, rn),
186
+ vec_reg_offset(s, rm, index, size), fpst,
187
+ is_q ? 16 : 8, vec_full_reg_size(s),
188
+ extract32(insn, 13, 2), /* rot */
189
+ size == MO_64
190
+ ? gen_helper_gvec_fcmlas_idx
191
+ : gen_helper_gvec_fcmlah_idx);
192
+ tcg_temp_free_ptr(fpst);
193
+ return;
194
+ }
195
+
196
if (size == 3) {
197
TCGv_i64 tcg_idx = tcg_temp_new_i64();
198
int pass;
199
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/target/arm/vec_helper.c
202
+++ b/target/arm/vec_helper.c
203
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_fcaddd)(void *vd, void *vn, void *vm,
204
}
205
clear_tail(d, opr_sz, simd_maxsz(desc));
206
}
207
+
208
+void HELPER(gvec_fcmlah)(void *vd, void *vn, void *vm,
209
+ void *vfpst, uint32_t desc)
210
+{
211
+ uintptr_t opr_sz = simd_oprsz(desc);
212
+ float16 *d = vd;
213
+ float16 *n = vn;
214
+ float16 *m = vm;
215
+ float_status *fpst = vfpst;
216
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
217
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
218
+ uint32_t neg_real = flip ^ neg_imag;
219
+ uintptr_t i;
220
+
221
+ /* Shift boolean to the sign bit so we can xor to negate. */
222
+ neg_real <<= 15;
223
+ neg_imag <<= 15;
224
+
225
+ for (i = 0; i < opr_sz / 2; i += 2) {
226
+ float16 e2 = n[H2(i + flip)];
227
+ float16 e1 = m[H2(i + flip)] ^ neg_real;
228
+ float16 e4 = e2;
229
+ float16 e3 = m[H2(i + 1 - flip)] ^ neg_imag;
230
+
231
+ d[H2(i)] = float16_muladd(e2, e1, d[H2(i)], 0, fpst);
232
+ d[H2(i + 1)] = float16_muladd(e4, e3, d[H2(i + 1)], 0, fpst);
233
+ }
234
+ clear_tail(d, opr_sz, simd_maxsz(desc));
235
+}
236
+
237
+void HELPER(gvec_fcmlah_idx)(void *vd, void *vn, void *vm,
238
+ void *vfpst, uint32_t desc)
239
+{
240
+ uintptr_t opr_sz = simd_oprsz(desc);
241
+ float16 *d = vd;
242
+ float16 *n = vn;
243
+ float16 *m = vm;
244
+ float_status *fpst = vfpst;
245
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
246
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
247
+ uint32_t neg_real = flip ^ neg_imag;
248
+ uintptr_t i;
249
+ float16 e1 = m[H2(flip)];
250
+ float16 e3 = m[H2(1 - flip)];
251
+
252
+ /* Shift boolean to the sign bit so we can xor to negate. */
253
+ neg_real <<= 15;
254
+ neg_imag <<= 15;
255
+ e1 ^= neg_real;
256
+ e3 ^= neg_imag;
257
+
258
+ for (i = 0; i < opr_sz / 2; i += 2) {
259
+ float16 e2 = n[H2(i + flip)];
260
+ float16 e4 = e2;
261
+
262
+ d[H2(i)] = float16_muladd(e2, e1, d[H2(i)], 0, fpst);
263
+ d[H2(i + 1)] = float16_muladd(e4, e3, d[H2(i + 1)], 0, fpst);
264
+ }
265
+ clear_tail(d, opr_sz, simd_maxsz(desc));
266
+}
267
+
268
+void HELPER(gvec_fcmlas)(void *vd, void *vn, void *vm,
269
+ void *vfpst, uint32_t desc)
270
+{
271
+ uintptr_t opr_sz = simd_oprsz(desc);
272
+ float32 *d = vd;
273
+ float32 *n = vn;
274
+ float32 *m = vm;
275
+ float_status *fpst = vfpst;
276
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
277
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
278
+ uint32_t neg_real = flip ^ neg_imag;
279
+ uintptr_t i;
280
+
281
+ /* Shift boolean to the sign bit so we can xor to negate. */
282
+ neg_real <<= 31;
283
+ neg_imag <<= 31;
284
+
285
+ for (i = 0; i < opr_sz / 4; i += 2) {
286
+ float32 e2 = n[H4(i + flip)];
287
+ float32 e1 = m[H4(i + flip)] ^ neg_real;
288
+ float32 e4 = e2;
289
+ float32 e3 = m[H4(i + 1 - flip)] ^ neg_imag;
290
+
291
+ d[H4(i)] = float32_muladd(e2, e1, d[H4(i)], 0, fpst);
292
+ d[H4(i + 1)] = float32_muladd(e4, e3, d[H4(i + 1)], 0, fpst);
293
+ }
294
+ clear_tail(d, opr_sz, simd_maxsz(desc));
295
+}
296
+
297
+void HELPER(gvec_fcmlas_idx)(void *vd, void *vn, void *vm,
298
+ void *vfpst, uint32_t desc)
299
+{
300
+ uintptr_t opr_sz = simd_oprsz(desc);
301
+ float32 *d = vd;
302
+ float32 *n = vn;
303
+ float32 *m = vm;
304
+ float_status *fpst = vfpst;
305
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
306
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
307
+ uint32_t neg_real = flip ^ neg_imag;
308
+ uintptr_t i;
309
+ float32 e1 = m[H4(flip)];
310
+ float32 e3 = m[H4(1 - flip)];
311
+
312
+ /* Shift boolean to the sign bit so we can xor to negate. */
313
+ neg_real <<= 31;
314
+ neg_imag <<= 31;
315
+ e1 ^= neg_real;
316
+ e3 ^= neg_imag;
317
+
318
+ for (i = 0; i < opr_sz / 4; i += 2) {
319
+ float32 e2 = n[H4(i + flip)];
320
+ float32 e4 = e2;
321
+
322
+ d[H4(i)] = float32_muladd(e2, e1, d[H4(i)], 0, fpst);
323
+ d[H4(i + 1)] = float32_muladd(e4, e3, d[H4(i + 1)], 0, fpst);
324
+ }
325
+ clear_tail(d, opr_sz, simd_maxsz(desc));
326
+}
327
+
328
+void HELPER(gvec_fcmlad)(void *vd, void *vn, void *vm,
329
+ void *vfpst, uint32_t desc)
330
+{
331
+ uintptr_t opr_sz = simd_oprsz(desc);
332
+ float64 *d = vd;
333
+ float64 *n = vn;
334
+ float64 *m = vm;
335
+ float_status *fpst = vfpst;
336
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
337
+ uint64_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
338
+ uint64_t neg_real = flip ^ neg_imag;
339
+ uintptr_t i;
340
+
341
+ /* Shift boolean to the sign bit so we can xor to negate. */
342
+ neg_real <<= 63;
343
+ neg_imag <<= 63;
344
+
345
+ for (i = 0; i < opr_sz / 8; i += 2) {
346
+ float64 e2 = n[i + flip];
347
+ float64 e1 = m[i + flip] ^ neg_real;
348
+ float64 e4 = e2;
349
+ float64 e3 = m[i + 1 - flip] ^ neg_imag;
350
+
351
+ d[i] = float64_muladd(e2, e1, d[i], 0, fpst);
352
+ d[i + 1] = float64_muladd(e4, e3, d[i + 1], 0, fpst);
353
+ }
354
+ clear_tail(d, opr_sz, simd_maxsz(desc));
355
+}
356
--
28
--
357
2.16.2
29
2.20.1
358
30
359
31
diff view generated by jsdifflib
1
The Cortex-M33 allows the system to specify the reset value of the
1
From: Andrew Jones <drjones@redhat.com>
2
secure Vector Table Offset Register (VTOR) by asserting config
3
signals. In particular, guest images for the MPS2 AN505 board rely
4
on the MPS2's initial VTOR being correct for that board.
5
Implement a QEMU property so board and SoC code can set the reset
6
value to the correct value.
7
2
3
Prior to commit f2ce39b4f067 a MachineClass kvm_type method
4
only needed to be registered to ensure it would be executed.
5
With commit f2ce39b4f067 a kvm-type machine property must also
6
be specified. hw/arm/virt relies on the kvm_type method to pass
7
its selected IPA limit to KVM, but this is not exposed as a
8
machine property. Restore the previous functionality of invoking
9
kvm_type when it's present.
10
11
Fixes: f2ce39b4f067 ("vl: make qemu_get_machine_opts static")
12
Signed-off-by: Andrew Jones <drjones@redhat.com>
13
Reviewed-by: Eric Auger <eric.auger@redhat.com>
14
Message-id: 20210310135218.255205-2-drjones@redhat.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180220180325.29818-7-peter.maydell@linaro.org
11
---
16
---
12
target/arm/cpu.h | 3 +++
17
include/hw/boards.h | 1 +
13
target/arm/cpu.c | 18 ++++++++++++++----
18
accel/kvm/kvm-all.c | 2 ++
14
2 files changed, 17 insertions(+), 4 deletions(-)
19
2 files changed, 3 insertions(+)
15
20
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
diff --git a/include/hw/boards.h b/include/hw/boards.h
17
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
23
--- a/include/hw/boards.h
19
+++ b/target/arm/cpu.h
24
+++ b/include/hw/boards.h
20
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
25
@@ -XXX,XX +XXX,XX @@ typedef struct {
21
*/
26
* @kvm_type:
22
uint32_t psci_conduit;
27
* Return the type of KVM corresponding to the kvm-type string option or
23
28
* computed based on other criteria such as the host kernel capabilities.
24
+ /* For v8M, initial value of the Secure VTOR */
29
+ * kvm-type may be NULL if it is not needed.
25
+ uint32_t init_svtor;
30
* @numa_mem_supported:
26
+
31
* true if '--numa node.mem' option is supported and false otherwise
27
/* [QEMU_]KVM_ARM_TARGET_* constant for this CPU, or
32
* @smp_parse:
28
* QEMU_KVM_ARM_TARGET_NONE if the kernel doesn't support this CPU type.
33
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
29
*/
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
31
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.c
35
--- a/accel/kvm/kvm-all.c
33
+++ b/target/arm/cpu.c
36
+++ b/accel/kvm/kvm-all.c
34
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
37
@@ -XXX,XX +XXX,XX @@ static int kvm_init(MachineState *ms)
35
uint32_t initial_msp; /* Loaded from 0x0 */
38
"kvm-type",
36
uint32_t initial_pc; /* Loaded from 0x4 */
39
&error_abort);
37
uint8_t *rom;
40
type = mc->kvm_type(ms, kvm_type);
38
+ uint32_t vecbase;
41
+ } else if (mc->kvm_type) {
39
42
+ type = mc->kvm_type(ms, NULL);
40
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
41
env->v7m.secure = true;
42
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
43
/* Unlike A/R profile, M profile defines the reset LR value */
44
env->regs[14] = 0xffffffff;
45
46
- /* Load the initial SP and PC from the vector table at address 0 */
47
- rom = rom_ptr(0);
48
+ env->v7m.vecbase[M_REG_S] = cpu->init_svtor & 0xffffff80;
49
+
50
+ /* Load the initial SP and PC from offset 0 and 4 in the vector table */
51
+ vecbase = env->v7m.vecbase[env->v7m.secure];
52
+ rom = rom_ptr(vecbase);
53
if (rom) {
54
/* Address zero is covered by ROM which hasn't yet been
55
* copied into physical memory.
56
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
57
* it got copied into memory. In the latter case, rom_ptr
58
* will return a NULL pointer and we should use ldl_phys instead.
59
*/
60
- initial_msp = ldl_phys(s->as, 0);
61
- initial_pc = ldl_phys(s->as, 4);
62
+ initial_msp = ldl_phys(s->as, vecbase);
63
+ initial_pc = ldl_phys(s->as, vecbase + 4);
64
}
65
66
env->regs[13] = initial_msp & 0xFFFFFFFC;
67
@@ -XXX,XX +XXX,XX @@ static Property arm_cpu_pmsav7_dregion_property =
68
pmsav7_dregion,
69
qdev_prop_uint32, uint32_t);
70
71
+/* M profile: initial value of the Secure VTOR */
72
+static Property arm_cpu_initsvtor_property =
73
+ DEFINE_PROP_UINT32("init-svtor", ARMCPU, init_svtor, 0);
74
+
75
static void arm_cpu_post_init(Object *obj)
76
{
77
ARMCPU *cpu = ARM_CPU(obj);
78
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_post_init(Object *obj)
79
qdev_prop_allow_set_link_before_realize,
80
OBJ_PROP_LINK_UNREF_ON_RELEASE,
81
&error_abort);
82
+ qdev_property_add_static(DEVICE(obj), &arm_cpu_initsvtor_property,
83
+ &error_abort);
84
}
43
}
85
44
86
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
45
do {
87
--
46
--
88
2.16.2
47
2.20.1
89
48
90
49
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Andrew Jones <drjones@redhat.com>
2
2
3
Allow the guest to determine the time set from the QEMU command line.
3
The virt machine already checks KVM_CAP_ARM_VM_IPA_SIZE to get the
4
upper bound of the IPA size. If that bound is lower than the highest
5
possible GPA for the machine, then QEMU will error out. However, the
6
IPA is set to 40 when the highest GPA is less than or equal to 40,
7
even when KVM may support an IPA limit as low as 32. This means KVM
8
may fail the VM creation unnecessarily. Additionally, 40 is selected
9
with the value 0, which means use the default, and that gets around
10
a check in some versions of KVM, causing a difficult to debug fail.
11
Always use the IPA size that corresponds to the highest possible GPA,
12
unless it's lower than 32, in which case use 32. Also, we must still
13
use 0 when KVM only supports the legacy fixed 40 bit IPA.
4
14
5
This includes adding a trace event to debug the new time.
15
Suggested-by: Marc Zyngier <maz@kernel.org>
6
16
Signed-off-by: Andrew Jones <drjones@redhat.com>
7
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
17
Reviewed-by: Eric Auger <eric.auger@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Reviewed-by: Marc Zyngier <maz@kernel.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Message-id: 20210310135218.255205-3-drjones@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
21
---
12
include/hw/timer/xlnx-zynqmp-rtc.h | 2 ++
22
target/arm/kvm_arm.h | 6 ++++--
13
hw/timer/xlnx-zynqmp-rtc.c | 58 ++++++++++++++++++++++++++++++++++++++
23
hw/arm/virt.c | 23 ++++++++++++++++-------
14
hw/timer/trace-events | 3 ++
24
target/arm/kvm.c | 4 +++-
15
3 files changed, 63 insertions(+)
25
3 files changed, 23 insertions(+), 10 deletions(-)
16
26
17
diff --git a/include/hw/timer/xlnx-zynqmp-rtc.h b/include/hw/timer/xlnx-zynqmp-rtc.h
27
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
18
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/timer/xlnx-zynqmp-rtc.h
29
--- a/target/arm/kvm_arm.h
20
+++ b/include/hw/timer/xlnx-zynqmp-rtc.h
30
+++ b/target/arm/kvm_arm.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct XlnxZynqMPRTC {
31
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_sve_supported(void);
22
qemu_irq irq_rtc_int;
32
/**
23
qemu_irq irq_addr_error_int;
33
* kvm_arm_get_max_vm_ipa_size:
24
34
* @ms: Machine state handle
25
+ uint32_t tick_offset;
35
+ * @fixed_ipa: True when the IPA limit is fixed at 40. This is the case
36
+ * for legacy KVM.
37
*
38
* Returns the number of bits in the IPA address space supported by KVM
39
*/
40
-int kvm_arm_get_max_vm_ipa_size(MachineState *ms);
41
+int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa);
42
43
/**
44
* kvm_arm_sync_mpstate_to_kvm:
45
@@ -XXX,XX +XXX,XX @@ static inline void kvm_arm_add_vcpu_properties(Object *obj)
46
g_assert_not_reached();
47
}
48
49
-static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
50
+static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa)
51
{
52
g_assert_not_reached();
53
}
54
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/arm/virt.c
57
+++ b/hw/arm/virt.c
58
@@ -XXX,XX +XXX,XX @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
59
static int virt_kvm_type(MachineState *ms, const char *type_str)
60
{
61
VirtMachineState *vms = VIRT_MACHINE(ms);
62
- int max_vm_pa_size = kvm_arm_get_max_vm_ipa_size(ms);
63
- int requested_pa_size;
64
+ int max_vm_pa_size, requested_pa_size;
65
+ bool fixed_ipa;
26
+
66
+
27
uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX];
67
+ max_vm_pa_size = kvm_arm_get_max_vm_ipa_size(ms, &fixed_ipa);
28
RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX];
68
29
} XlnxZynqMPRTC;
69
/* we freeze the memory map to compute the highest gpa */
30
diff --git a/hw/timer/xlnx-zynqmp-rtc.c b/hw/timer/xlnx-zynqmp-rtc.c
70
virt_set_memmap(vms);
71
72
requested_pa_size = 64 - clz64(vms->highest_gpa);
73
74
+ /*
75
+ * KVM requires the IPA size to be at least 32 bits.
76
+ */
77
+ if (requested_pa_size < 32) {
78
+ requested_pa_size = 32;
79
+ }
80
+
81
if (requested_pa_size > max_vm_pa_size) {
82
error_report("-m and ,maxmem option values "
83
"require an IPA range (%d bits) larger than "
84
"the one supported by the host (%d bits)",
85
requested_pa_size, max_vm_pa_size);
86
- exit(1);
87
+ exit(1);
88
}
89
/*
90
- * By default we return 0 which corresponds to an implicit legacy
91
- * 40b IPA setting. Otherwise we return the actual requested PA
92
- * logsize
93
+ * We return the requested PA log size, unless KVM only supports
94
+ * the implicit legacy 40b IPA setting, in which case the kvm_type
95
+ * must be 0.
96
*/
97
- return requested_pa_size > 40 ? requested_pa_size : 0;
98
+ return fixed_ipa ? 0 : requested_pa_size;
99
}
100
101
static void virt_machine_class_init(ObjectClass *oc, void *data)
102
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
31
index XXXXXXX..XXXXXXX 100644
103
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/timer/xlnx-zynqmp-rtc.c
104
--- a/target/arm/kvm.c
33
+++ b/hw/timer/xlnx-zynqmp-rtc.c
105
+++ b/target/arm/kvm.c
34
@@ -XXX,XX +XXX,XX @@
106
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_pmu_supported(void)
35
#include "hw/register.h"
107
return kvm_check_extension(kvm_state, KVM_CAP_ARM_PMU_V3);
36
#include "qemu/bitops.h"
37
#include "qemu/log.h"
38
+#include "hw/ptimer.h"
39
+#include "qemu/cutils.h"
40
+#include "sysemu/sysemu.h"
41
+#include "trace.h"
42
#include "hw/timer/xlnx-zynqmp-rtc.h"
43
44
#ifndef XLNX_ZYNQMP_RTC_ERR_DEBUG
45
@@ -XXX,XX +XXX,XX @@ static void addr_error_int_update_irq(XlnxZynqMPRTC *s)
46
qemu_set_irq(s->irq_addr_error_int, pending);
47
}
108
}
48
109
49
+static uint32_t rtc_get_count(XlnxZynqMPRTC *s)
110
-int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
50
+{
111
+int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa)
51
+ int64_t now = qemu_clock_get_ns(rtc_clock);
112
{
52
+ return s->tick_offset + now / NANOSECONDS_PER_SECOND;
113
KVMState *s = KVM_STATE(ms->accelerator);
53
+}
114
int ret;
115
116
ret = kvm_check_extension(s, KVM_CAP_ARM_VM_IPA_SIZE);
117
+ *fixed_ipa = ret <= 0;
54
+
118
+
55
+static uint64_t current_time_postr(RegisterInfo *reg, uint64_t val64)
119
return ret > 0 ? ret : 40;
56
+{
57
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
58
+
59
+ return rtc_get_count(s);
60
+}
61
+
62
static void rtc_int_status_postw(RegisterInfo *reg, uint64_t val64)
63
{
64
XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
65
@@ -XXX,XX +XXX,XX @@ static uint64_t addr_error_int_dis_prew(RegisterInfo *reg, uint64_t val64)
66
67
static const RegisterAccessInfo rtc_regs_info[] = {
68
{ .name = "SET_TIME_WRITE", .addr = A_SET_TIME_WRITE,
69
+ .unimp = MAKE_64BIT_MASK(0, 32),
70
},{ .name = "SET_TIME_READ", .addr = A_SET_TIME_READ,
71
.ro = 0xffffffff,
72
+ .post_read = current_time_postr,
73
},{ .name = "CALIB_WRITE", .addr = A_CALIB_WRITE,
74
+ .unimp = MAKE_64BIT_MASK(0, 32),
75
},{ .name = "CALIB_READ", .addr = A_CALIB_READ,
76
.ro = 0x1fffff,
77
},{ .name = "CURRENT_TIME", .addr = A_CURRENT_TIME,
78
.ro = 0xffffffff,
79
+ .post_read = current_time_postr,
80
},{ .name = "CURRENT_TICK", .addr = A_CURRENT_TICK,
81
.ro = 0xffff,
82
},{ .name = "ALARM", .addr = A_ALARM,
83
@@ -XXX,XX +XXX,XX @@ static void rtc_init(Object *obj)
84
XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(obj);
85
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
86
RegisterInfoArray *reg_array;
87
+ struct tm current_tm;
88
89
memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_RTC,
90
XLNX_ZYNQMP_RTC_R_MAX * 4);
91
@@ -XXX,XX +XXX,XX @@ static void rtc_init(Object *obj)
92
sysbus_init_mmio(sbd, &s->iomem);
93
sysbus_init_irq(sbd, &s->irq_rtc_int);
94
sysbus_init_irq(sbd, &s->irq_addr_error_int);
95
+
96
+ qemu_get_timedate(&current_tm, 0);
97
+ s->tick_offset = mktimegm(&current_tm) -
98
+ qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
99
+
100
+ trace_xlnx_zynqmp_rtc_gettime(current_tm.tm_year, current_tm.tm_mon,
101
+ current_tm.tm_mday, current_tm.tm_hour,
102
+ current_tm.tm_min, current_tm.tm_sec);
103
+}
104
+
105
+static int rtc_pre_save(void *opaque)
106
+{
107
+ XlnxZynqMPRTC *s = opaque;
108
+ int64_t now = qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
109
+
110
+ /* Add the time at migration */
111
+ s->tick_offset = s->tick_offset + now;
112
+
113
+ return 0;
114
+}
115
+
116
+static int rtc_post_load(void *opaque, int version_id)
117
+{
118
+ XlnxZynqMPRTC *s = opaque;
119
+ int64_t now = qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
120
+
121
+ /* Subtract the time after migration. This combined with the pre_save
122
+ * action results in us having subtracted the time that the guest was
123
+ * stopped to the offset.
124
+ */
125
+ s->tick_offset = s->tick_offset - now;
126
+
127
+ return 0;
128
}
120
}
129
121
130
static const VMStateDescription vmstate_rtc = {
131
.name = TYPE_XLNX_ZYNQMP_RTC,
132
.version_id = 1,
133
.minimum_version_id = 1,
134
+ .pre_save = rtc_pre_save,
135
+ .post_load = rtc_post_load,
136
.fields = (VMStateField[]) {
137
VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPRTC, XLNX_ZYNQMP_RTC_R_MAX),
138
+ VMSTATE_UINT32(tick_offset, XlnxZynqMPRTC),
139
VMSTATE_END_OF_LIST(),
140
}
141
};
142
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
143
index XXXXXXX..XXXXXXX 100644
144
--- a/hw/timer/trace-events
145
+++ b/hw/timer/trace-events
146
@@ -XXX,XX +XXX,XX @@ systick_write(uint64_t addr, uint32_t value, unsigned size) "systick write addr
147
cmsdk_apb_timer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
148
cmsdk_apb_timer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
149
cmsdk_apb_timer_reset(void) "CMSDK APB timer: reset"
150
+
151
+# hw/timer/xlnx-zynqmp-rtc.c
152
+xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec) "Get time from host: %d-%d-%d %2d:%02d:%02d"
153
--
122
--
154
2.16.2
123
2.20.1
155
124
156
125
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
3
This patch adds GPIOs in NPCM7xx PWM module for its duty values.
4
The purpose of this is to connect it to the MFT module to provide
5
an input for measuring a PWM fan's RPM. Each PWM module has
6
NPCM7XX_PWM_PER_MODULE of GPIOs, each one corresponds to
7
one PWM instance and can connect to multiple fan instances in MFT.
8
9
Reviewed-by: Doug Evans <dje@google.com>
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
Signed-off-by: Hao Wu <wuhaotsh@google.com>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 20210311180855.149764-2-wuhaotsh@google.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
15
---
8
include/hw/arm/xlnx-zynqmp.h | 2 ++
16
include/hw/misc/npcm7xx_pwm.h | 4 +++-
9
hw/arm/xlnx-zynqmp.c | 14 ++++++++++++++
17
hw/misc/npcm7xx_pwm.c | 4 ++++
10
2 files changed, 16 insertions(+)
18
2 files changed, 7 insertions(+), 1 deletion(-)
11
19
12
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
20
diff --git a/include/hw/misc/npcm7xx_pwm.h b/include/hw/misc/npcm7xx_pwm.h
13
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/xlnx-zynqmp.h
22
--- a/include/hw/misc/npcm7xx_pwm.h
15
+++ b/include/hw/arm/xlnx-zynqmp.h
23
+++ b/include/hw/misc/npcm7xx_pwm.h
16
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxPWM {
17
#include "hw/dma/xlnx_dpdma.h"
25
* @iomem: Memory region through which registers are accessed.
18
#include "hw/display/xlnx_dp.h"
26
* @clock: The PWM clock.
19
#include "hw/intc/xlnx-zynqmp-ipi.h"
27
* @pwm: The PWM channels owned by this module.
20
+#include "hw/timer/xlnx-zynqmp-rtc.h"
28
+ * @duty_gpio_out: The duty cycle of each PWM channels as a output GPIO.
21
29
* @ppr: The prescaler register.
22
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
30
* @csr: The clock selector register.
23
#define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
31
* @pcr: The control register.
24
@@ -XXX,XX +XXX,XX @@ typedef struct XlnxZynqMPState {
32
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxPWMState {
25
XlnxDPState dp;
33
MemoryRegion iomem;
26
XlnxDPDMAState dpdma;
34
27
XlnxZynqMPIPI ipi;
35
Clock *clock;
28
+ XlnxZynqMPRTC rtc;
36
- NPCM7xxPWM pwm[NPCM7XX_PWM_PER_MODULE];
29
37
+ NPCM7xxPWM pwm[NPCM7XX_PWM_PER_MODULE];
30
char *boot_cpu;
38
+ qemu_irq duty_gpio_out[NPCM7XX_PWM_PER_MODULE];
31
ARMCPU *boot_cpu_ptr;
39
32
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
40
uint32_t ppr;
41
uint32_t csr;
42
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
33
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/xlnx-zynqmp.c
44
--- a/hw/misc/npcm7xx_pwm.c
35
+++ b/hw/arm/xlnx-zynqmp.c
45
+++ b/hw/misc/npcm7xx_pwm.c
36
@@ -XXX,XX +XXX,XX @@
46
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_update_duty(NPCM7xxPWM *p)
37
#define IPI_ADDR 0xFF300000
47
trace_npcm7xx_pwm_update_duty(DEVICE(p->module)->canonical_path,
38
#define IPI_IRQ 64
48
p->index, p->duty, duty);
39
49
p->duty = duty;
40
+#define RTC_ADDR 0xffa60000
50
+ qemu_set_irq(p->module->duty_gpio_out[p->index], p->duty);
41
+#define RTC_IRQ 26
51
}
42
+
43
#define SDHCI_CAPABILITIES 0x280737ec6481 /* Datasheet: UG1085 (v1.7) */
44
45
static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = {
46
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
47
48
object_initialize(&s->ipi, sizeof(s->ipi), TYPE_XLNX_ZYNQMP_IPI);
49
qdev_set_parent_bus(DEVICE(&s->ipi), sysbus_get_default());
50
+
51
+ object_initialize(&s->rtc, sizeof(s->rtc), TYPE_XLNX_ZYNQMP_RTC);
52
+ qdev_set_parent_bus(DEVICE(&s->rtc), sysbus_get_default());
53
}
52
}
54
53
55
static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
54
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_init(Object *obj)
56
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
55
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
56
int i;
57
58
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->pwm) != NPCM7XX_PWM_PER_MODULE);
59
for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
60
NPCM7xxPWM *p = &s->pwm[i];
61
p->module = s;
62
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_init(Object *obj)
63
object_property_add_uint32_ptr(obj, "duty[*]",
64
&s->pwm[i].duty, OBJ_PROP_FLAG_READ);
57
}
65
}
58
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ipi), 0, IPI_ADDR);
66
+ qdev_init_gpio_out_named(DEVICE(s), s->duty_gpio_out,
59
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ipi), 0, gic_spi[IPI_IRQ]);
67
+ "duty-gpio-out", NPCM7XX_PWM_PER_MODULE);
60
+
61
+ object_property_set_bool(OBJECT(&s->rtc), true, "realized", &err);
62
+ if (err) {
63
+ error_propagate(errp, err);
64
+ return;
65
+ }
66
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, RTC_ADDR);
67
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0, gic_spi[RTC_IRQ]);
68
}
68
}
69
69
70
static Property xlnx_zynqmp_props[] = {
70
static const VMStateDescription vmstate_npcm7xx_pwm = {
71
--
71
--
72
2.16.2
72
2.20.1
73
73
74
74
diff view generated by jsdifflib
1
In some board or SoC models it is necessary to split a qemu_irq line
1
From: Hao Wu <wuhaotsh@google.com>
2
so that one input can feed multiple outputs. We currently have
3
qemu_irq_split() for this, but that has several deficiencies:
4
* it can only handle splitting a line into two
5
* it unavoidably leaks memory, so it can't be used
6
in a device that can be deleted
7
2
8
Implement a qdev device that encapsulates splitting of IRQs, with a
3
This patch implements Multi Function Timer (MFT) module for NPCM7XX.
9
configurable number of outputs. (This is in some ways the inverse of
4
This module is mainly used to configure PWM fans. It has just enough
10
the TYPE_OR_IRQ device.)
5
functionality to make the PWM fan kernel module work.
11
6
7
The module takes two input, the max_rpm of a fan (modifiable via QMP)
8
and duty cycle (a GPIO from the PWM module.) The actual measured RPM
9
is equal to max_rpm * duty_cycle / NPCM7XX_PWM_MAX_DUTY. The RPM is
10
measured as a counter compared to a prescaled input clock. The kernel
11
driver reads this counter and report to user space.
12
13
Refs:
14
https://github.com/torvalds/linux/blob/master/drivers/hwmon/npcm750-pwm-fan.c
15
16
Reviewed-by: Doug Evans <dje@google.com>
17
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
18
Signed-off-by: Hao Wu <wuhaotsh@google.com>
19
Message-id: 20210311180855.149764-3-wuhaotsh@google.com
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20180220180325.29818-13-peter.maydell@linaro.org
15
---
22
---
16
hw/core/Makefile.objs | 1 +
23
include/hw/misc/npcm7xx_mft.h | 70 +++++
17
include/hw/core/split-irq.h | 57 +++++++++++++++++++++++++++++
24
hw/misc/npcm7xx_mft.c | 540 ++++++++++++++++++++++++++++++++++
18
include/hw/irq.h | 4 +-
25
hw/misc/meson.build | 1 +
19
hw/core/split-irq.c | 89 +++++++++++++++++++++++++++++++++++++++++++++
26
hw/misc/trace-events | 8 +
20
4 files changed, 150 insertions(+), 1 deletion(-)
27
4 files changed, 619 insertions(+)
21
create mode 100644 include/hw/core/split-irq.h
28
create mode 100644 include/hw/misc/npcm7xx_mft.h
22
create mode 100644 hw/core/split-irq.c
29
create mode 100644 hw/misc/npcm7xx_mft.c
23
30
24
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
31
diff --git a/include/hw/misc/npcm7xx_mft.h b/include/hw/misc/npcm7xx_mft.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/core/Makefile.objs
27
+++ b/hw/core/Makefile.objs
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_FITLOADER) += loader-fit.o
29
common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o
30
common-obj-$(CONFIG_SOFTMMU) += register.o
31
common-obj-$(CONFIG_SOFTMMU) += or-irq.o
32
+common-obj-$(CONFIG_SOFTMMU) += split-irq.o
33
common-obj-$(CONFIG_PLATFORM_BUS) += platform-bus.o
34
35
obj-$(CONFIG_SOFTMMU) += generic-loader.o
36
diff --git a/include/hw/core/split-irq.h b/include/hw/core/split-irq.h
37
new file mode 100644
32
new file mode 100644
38
index XXXXXXX..XXXXXXX
33
index XXXXXXX..XXXXXXX
39
--- /dev/null
34
--- /dev/null
40
+++ b/include/hw/core/split-irq.h
35
+++ b/include/hw/misc/npcm7xx_mft.h
41
@@ -XXX,XX +XXX,XX @@
36
@@ -XXX,XX +XXX,XX @@
42
+/*
37
+/*
43
+ * IRQ splitter device.
38
+ * Nuvoton NPCM7xx MFT Module
44
+ *
39
+ *
45
+ * Copyright (c) 2018 Linaro Limited.
40
+ * Copyright 2021 Google LLC
46
+ * Written by Peter Maydell
47
+ *
41
+ *
48
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
42
+ * This program is free software; you can redistribute it and/or modify it
49
+ * of this software and associated documentation files (the "Software"), to deal
43
+ * under the terms of the GNU General Public License as published by the
50
+ * in the Software without restriction, including without limitation the rights
44
+ * Free Software Foundation; either version 2 of the License, or
51
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
45
+ * (at your option) any later version.
52
+ * copies of the Software, and to permit persons to whom the Software is
53
+ * furnished to do so, subject to the following conditions:
54
+ *
46
+ *
55
+ * The above copyright notice and this permission notice shall be included in
47
+ * This program is distributed in the hope that it will be useful, but WITHOUT
56
+ * all copies or substantial portions of the Software.
48
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
57
+ *
49
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
58
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
50
+ * for more details.
59
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
51
+ */
60
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
52
+#ifndef NPCM7XX_MFT_H
61
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
53
+#define NPCM7XX_MFT_H
62
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
54
+
63
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
55
+#include "exec/memory.h"
64
+ * THE SOFTWARE.
56
+#include "hw/clock.h"
65
+ */
66
+
67
+/* This is a simple device which has one GPIO input line and multiple
68
+ * GPIO output lines. Any change on the input line is forwarded to all
69
+ * of the outputs.
70
+ *
71
+ * QEMU interface:
72
+ * + one unnamed GPIO input: the input line
73
+ * + N unnamed GPIO outputs: the output lines
74
+ * + QOM property "num-lines": sets the number of output lines
75
+ */
76
+#ifndef HW_SPLIT_IRQ_H
77
+#define HW_SPLIT_IRQ_H
78
+
79
+#include "hw/irq.h"
57
+#include "hw/irq.h"
80
+#include "hw/sysbus.h"
58
+#include "hw/sysbus.h"
81
+#include "qom/object.h"
59
+#include "qom/object.h"
82
+
60
+
83
+#define TYPE_SPLIT_IRQ "split-irq"
61
+/* Max Fan input number. */
84
+
62
+#define NPCM7XX_MFT_MAX_FAN_INPUT 19
85
+#define MAX_SPLIT_LINES 16
63
+
86
+
64
+/*
87
+typedef struct SplitIRQ SplitIRQ;
65
+ * Number of registers in one MFT module. Don't change this without increasing
88
+
66
+ * the version_id in vmstate.
89
+#define SPLIT_IRQ(obj) OBJECT_CHECK(SplitIRQ, (obj), TYPE_SPLIT_IRQ)
67
+ */
90
+
68
+#define NPCM7XX_MFT_NR_REGS (0x20 / sizeof(uint16_t))
91
+struct SplitIRQ {
69
+
92
+ DeviceState parent_obj;
70
+/*
93
+
71
+ * The MFT can take up to 4 inputs: A0, B0, A1, B1. It can measure one A and one
94
+ qemu_irq out_irq[MAX_SPLIT_LINES];
72
+ * B simultaneously. NPCM7XX_MFT_INASEL and NPCM7XX_MFT_INBSEL are used to
95
+ uint16_t num_lines;
73
+ * select which A or B input are used.
96
+};
74
+ */
97
+
75
+#define NPCM7XX_MFT_FANIN_COUNT 4
98
+#endif
76
+
99
diff --git a/include/hw/irq.h b/include/hw/irq.h
77
+/**
100
index XXXXXXX..XXXXXXX 100644
78
+ * struct NPCM7xxMFTState - Multi Functional Tachometer device state.
101
--- a/include/hw/irq.h
79
+ * @parent: System bus device.
102
+++ b/include/hw/irq.h
80
+ * @iomem: Memory region through which registers are accessed.
103
@@ -XXX,XX +XXX,XX @@ void qemu_free_irq(qemu_irq irq);
81
+ * @clock_in: The input clock for MFT from CLK module.
104
/* Returns a new IRQ with opposite polarity. */
82
+ * @clock_{1,2}: The counter clocks for NPCM7XX_MFT_CNT{1,2}
105
qemu_irq qemu_irq_invert(qemu_irq irq);
83
+ * @irq: The IRQ for this MFT state.
106
84
+ * @regs: The MMIO registers.
107
-/* Returns a new IRQ which feeds into both the passed IRQs */
85
+ * @max_rpm: The maximum rpm for fans. Order: A0, B0, A1, B1.
108
+/* Returns a new IRQ which feeds into both the passed IRQs.
86
+ * @duty: The duty cycles for fans, relative to NPCM7XX_PWM_MAX_DUTY.
109
+ * It's probably better to use the TYPE_SPLIT_IRQ device instead.
87
+ */
110
+ */
88
+typedef struct NPCM7xxMFTState {
111
qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
89
+ SysBusDevice parent;
112
90
+
113
/* Returns a new IRQ set which connects 1:1 to another IRQ set, which
91
+ MemoryRegion iomem;
114
diff --git a/hw/core/split-irq.c b/hw/core/split-irq.c
92
+
93
+ Clock *clock_in;
94
+ Clock *clock_1, *clock_2;
95
+ qemu_irq irq;
96
+ uint16_t regs[NPCM7XX_MFT_NR_REGS];
97
+
98
+ uint32_t max_rpm[NPCM7XX_MFT_FANIN_COUNT];
99
+ uint32_t duty[NPCM7XX_MFT_FANIN_COUNT];
100
+} NPCM7xxMFTState;
101
+
102
+#define TYPE_NPCM7XX_MFT "npcm7xx-mft"
103
+#define NPCM7XX_MFT(obj) \
104
+ OBJECT_CHECK(NPCM7xxMFTState, (obj), TYPE_NPCM7XX_MFT)
105
+
106
+#endif /* NPCM7XX_MFT_H */
107
diff --git a/hw/misc/npcm7xx_mft.c b/hw/misc/npcm7xx_mft.c
115
new file mode 100644
108
new file mode 100644
116
index XXXXXXX..XXXXXXX
109
index XXXXXXX..XXXXXXX
117
--- /dev/null
110
--- /dev/null
118
+++ b/hw/core/split-irq.c
111
+++ b/hw/misc/npcm7xx_mft.c
119
@@ -XXX,XX +XXX,XX @@
112
@@ -XXX,XX +XXX,XX @@
120
+/*
113
+/*
121
+ * IRQ splitter device.
114
+ * Nuvoton NPCM7xx MFT Module
122
+ *
115
+ *
123
+ * Copyright (c) 2018 Linaro Limited.
116
+ * Copyright 2021 Google LLC
124
+ * Written by Peter Maydell
125
+ *
117
+ *
126
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
118
+ * This program is free software; you can redistribute it and/or modify it
127
+ * of this software and associated documentation files (the "Software"), to deal
119
+ * under the terms of the GNU General Public License as published by the
128
+ * in the Software without restriction, including without limitation the rights
120
+ * Free Software Foundation; either version 2 of the License, or
129
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
121
+ * (at your option) any later version.
130
+ * copies of the Software, and to permit persons to whom the Software is
131
+ * furnished to do so, subject to the following conditions:
132
+ *
122
+ *
133
+ * The above copyright notice and this permission notice shall be included in
123
+ * This program is distributed in the hope that it will be useful, but WITHOUT
134
+ * all copies or substantial portions of the Software.
124
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
135
+ *
125
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
136
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
126
+ * for more details.
137
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
138
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
139
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
140
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
141
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
142
+ * THE SOFTWARE.
143
+ */
127
+ */
144
+
128
+
145
+#include "qemu/osdep.h"
129
+#include "qemu/osdep.h"
146
+#include "hw/core/split-irq.h"
130
+#include "hw/irq.h"
131
+#include "hw/qdev-clock.h"
132
+#include "hw/qdev-properties.h"
133
+#include "hw/misc/npcm7xx_mft.h"
134
+#include "hw/misc/npcm7xx_pwm.h"
135
+#include "hw/registerfields.h"
136
+#include "migration/vmstate.h"
147
+#include "qapi/error.h"
137
+#include "qapi/error.h"
148
+
138
+#include "qapi/visitor.h"
149
+static void split_irq_handler(void *opaque, int n, int level)
139
+#include "qemu/bitops.h"
150
+{
140
+#include "qemu/error-report.h"
151
+ SplitIRQ *s = SPLIT_IRQ(opaque);
141
+#include "qemu/log.h"
142
+#include "qemu/module.h"
143
+#include "qemu/timer.h"
144
+#include "qemu/units.h"
145
+#include "trace.h"
146
+
147
+/*
148
+ * Some of the registers can only accessed via 16-bit ops and some can only
149
+ * be accessed via 8-bit ops. However we mark all of them using REG16 to
150
+ * simplify implementation. npcm7xx_mft_check_mem_op checks the access length
151
+ * of memory operations.
152
+ */
153
+REG16(NPCM7XX_MFT_CNT1, 0x00);
154
+REG16(NPCM7XX_MFT_CRA, 0x02);
155
+REG16(NPCM7XX_MFT_CRB, 0x04);
156
+REG16(NPCM7XX_MFT_CNT2, 0x06);
157
+REG16(NPCM7XX_MFT_PRSC, 0x08);
158
+REG16(NPCM7XX_MFT_CKC, 0x0a);
159
+REG16(NPCM7XX_MFT_MCTRL, 0x0c);
160
+REG16(NPCM7XX_MFT_ICTRL, 0x0e);
161
+REG16(NPCM7XX_MFT_ICLR, 0x10);
162
+REG16(NPCM7XX_MFT_IEN, 0x12);
163
+REG16(NPCM7XX_MFT_CPA, 0x14);
164
+REG16(NPCM7XX_MFT_CPB, 0x16);
165
+REG16(NPCM7XX_MFT_CPCFG, 0x18);
166
+REG16(NPCM7XX_MFT_INASEL, 0x1a);
167
+REG16(NPCM7XX_MFT_INBSEL, 0x1c);
168
+
169
+/* Register Fields */
170
+#define NPCM7XX_MFT_CKC_C2CSEL BIT(3)
171
+#define NPCM7XX_MFT_CKC_C1CSEL BIT(0)
172
+
173
+#define NPCM7XX_MFT_MCTRL_TBEN BIT(6)
174
+#define NPCM7XX_MFT_MCTRL_TAEN BIT(5)
175
+#define NPCM7XX_MFT_MCTRL_TBEDG BIT(4)
176
+#define NPCM7XX_MFT_MCTRL_TAEDG BIT(3)
177
+#define NPCM7XX_MFT_MCTRL_MODE5 BIT(2)
178
+
179
+#define NPCM7XX_MFT_ICTRL_TFPND BIT(5)
180
+#define NPCM7XX_MFT_ICTRL_TEPND BIT(4)
181
+#define NPCM7XX_MFT_ICTRL_TDPND BIT(3)
182
+#define NPCM7XX_MFT_ICTRL_TCPND BIT(2)
183
+#define NPCM7XX_MFT_ICTRL_TBPND BIT(1)
184
+#define NPCM7XX_MFT_ICTRL_TAPND BIT(0)
185
+
186
+#define NPCM7XX_MFT_ICLR_TFCLR BIT(5)
187
+#define NPCM7XX_MFT_ICLR_TECLR BIT(4)
188
+#define NPCM7XX_MFT_ICLR_TDCLR BIT(3)
189
+#define NPCM7XX_MFT_ICLR_TCCLR BIT(2)
190
+#define NPCM7XX_MFT_ICLR_TBCLR BIT(1)
191
+#define NPCM7XX_MFT_ICLR_TACLR BIT(0)
192
+
193
+#define NPCM7XX_MFT_IEN_TFIEN BIT(5)
194
+#define NPCM7XX_MFT_IEN_TEIEN BIT(4)
195
+#define NPCM7XX_MFT_IEN_TDIEN BIT(3)
196
+#define NPCM7XX_MFT_IEN_TCIEN BIT(2)
197
+#define NPCM7XX_MFT_IEN_TBIEN BIT(1)
198
+#define NPCM7XX_MFT_IEN_TAIEN BIT(0)
199
+
200
+#define NPCM7XX_MFT_CPCFG_GET_B(rv) extract8((rv), 4, 4)
201
+#define NPCM7XX_MFT_CPCFG_GET_A(rv) extract8((rv), 0, 4)
202
+#define NPCM7XX_MFT_CPCFG_HIEN BIT(3)
203
+#define NPCM7XX_MFT_CPCFG_EQEN BIT(2)
204
+#define NPCM7XX_MFT_CPCFG_LOEN BIT(1)
205
+#define NPCM7XX_MFT_CPCFG_CPSEL BIT(0)
206
+
207
+#define NPCM7XX_MFT_INASEL_SELA BIT(0)
208
+#define NPCM7XX_MFT_INBSEL_SELB BIT(0)
209
+
210
+/* Max CNT values of the module. The CNT value is a countdown from it. */
211
+#define NPCM7XX_MFT_MAX_CNT 0xFFFF
212
+
213
+/* Each fan revolution should generated 2 pulses */
214
+#define NPCM7XX_MFT_PULSE_PER_REVOLUTION 2
215
+
216
+typedef enum NPCM7xxMFTCaptureState {
217
+ /* capture succeeded with a valid CNT value. */
218
+ NPCM7XX_CAPTURE_SUCCEED,
219
+ /* capture stopped prematurely due to reaching CPCFG condition. */
220
+ NPCM7XX_CAPTURE_COMPARE_HIT,
221
+ /* capture fails since it reaches underflow condition for CNT. */
222
+ NPCM7XX_CAPTURE_UNDERFLOW,
223
+} NPCM7xxMFTCaptureState;
224
+
225
+static void npcm7xx_mft_reset(NPCM7xxMFTState *s)
226
+{
152
+ int i;
227
+ int i;
153
+
228
+
154
+ for (i = 0; i < s->num_lines; i++) {
229
+ /* Only registers PRSC ~ INBSEL need to be reset. */
155
+ qemu_set_irq(s->out_irq[i], level);
230
+ for (i = R_NPCM7XX_MFT_PRSC; i <= R_NPCM7XX_MFT_INBSEL; ++i) {
156
+ }
231
+ s->regs[i] = 0;
157
+}
232
+ }
158
+
233
+}
159
+static void split_irq_init(Object *obj)
234
+
160
+{
235
+static void npcm7xx_mft_clear_interrupt(NPCM7xxMFTState *s, uint8_t iclr)
161
+ qdev_init_gpio_in(DEVICE(obj), split_irq_handler, 1);
236
+{
162
+}
237
+ /*
163
+
238
+ * Clear bits in ICTRL where corresponding bits in iclr is 1.
164
+static void split_irq_realize(DeviceState *dev, Error **errp)
239
+ * Both iclr and ictrl are 8-bit regs. (See npcm7xx_mft_check_mem_op)
165
+{
240
+ */
166
+ SplitIRQ *s = SPLIT_IRQ(dev);
241
+ s->regs[R_NPCM7XX_MFT_ICTRL] &= ~iclr;
167
+
242
+}
168
+ if (s->num_lines < 1 || s->num_lines >= MAX_SPLIT_LINES) {
243
+
169
+ error_setg(errp,
244
+/*
170
+ "IRQ splitter number of lines %d is not between 1 and %d",
245
+ * If the CPCFG's condition should be triggered during count down from
171
+ s->num_lines, MAX_SPLIT_LINES);
246
+ * NPCM7XX_MFT_MAX_CNT to src if compared to tgt, return the count when
247
+ * the condition is triggered.
248
+ * Otherwise return -1.
249
+ * Since tgt is uint16_t it must always <= NPCM7XX_MFT_MAX_CNT.
250
+ */
251
+static int npcm7xx_mft_compare(int32_t src, uint16_t tgt, uint8_t cpcfg)
252
+{
253
+ if (cpcfg & NPCM7XX_MFT_CPCFG_HIEN) {
254
+ return NPCM7XX_MFT_MAX_CNT;
255
+ }
256
+ if ((cpcfg & NPCM7XX_MFT_CPCFG_EQEN) && (src <= tgt)) {
257
+ return tgt;
258
+ }
259
+ if ((cpcfg & NPCM7XX_MFT_CPCFG_LOEN) && (tgt > 0) && (src < tgt)) {
260
+ return tgt - 1;
261
+ }
262
+
263
+ return -1;
264
+}
265
+
266
+/* Compute CNT according to corresponding fan's RPM. */
267
+static NPCM7xxMFTCaptureState npcm7xx_mft_compute_cnt(
268
+ Clock *clock, uint32_t max_rpm, uint32_t duty, uint16_t tgt,
269
+ uint8_t cpcfg, uint16_t *cnt)
270
+{
271
+ uint32_t rpm = (uint64_t)max_rpm * (uint64_t)duty / NPCM7XX_PWM_MAX_DUTY;
272
+ int32_t count;
273
+ int stopped;
274
+ NPCM7xxMFTCaptureState state;
275
+
276
+ if (rpm == 0) {
277
+ /*
278
+ * If RPM = 0, capture won't happen. CNT will continue count down.
279
+ * So it's effective equivalent to have a cnt > NPCM7XX_MFT_MAX_CNT
280
+ */
281
+ count = NPCM7XX_MFT_MAX_CNT + 1;
282
+ } else {
283
+ /*
284
+ * RPM = revolution/min. The time for one revlution (in ns) is
285
+ * MINUTE_TO_NANOSECOND / RPM.
286
+ */
287
+ count = clock_ns_to_ticks(clock, (60 * NANOSECONDS_PER_SECOND) /
288
+ (rpm * NPCM7XX_MFT_PULSE_PER_REVOLUTION));
289
+ }
290
+
291
+ if (count > NPCM7XX_MFT_MAX_CNT) {
292
+ count = -1;
293
+ } else {
294
+ /* The CNT is a countdown value from NPCM7XX_MFT_MAX_CNT. */
295
+ count = NPCM7XX_MFT_MAX_CNT - count;
296
+ }
297
+ stopped = npcm7xx_mft_compare(count, tgt, cpcfg);
298
+ if (stopped == -1) {
299
+ if (count == -1) {
300
+ /* Underflow */
301
+ state = NPCM7XX_CAPTURE_UNDERFLOW;
302
+ } else {
303
+ state = NPCM7XX_CAPTURE_SUCCEED;
304
+ }
305
+ } else {
306
+ count = stopped;
307
+ state = NPCM7XX_CAPTURE_COMPARE_HIT;
308
+ }
309
+
310
+ if (count != -1) {
311
+ *cnt = count;
312
+ }
313
+ trace_npcm7xx_mft_rpm(clock->canonical_path, clock_get_hz(clock),
314
+ state, count, rpm, duty);
315
+ return state;
316
+}
317
+
318
+/*
319
+ * Capture Fan RPM and update CNT and CR registers accordingly.
320
+ * Raise IRQ if certain contidions are met in IEN.
321
+ */
322
+static void npcm7xx_mft_capture(NPCM7xxMFTState *s)
323
+{
324
+ int irq_level = 0;
325
+ NPCM7xxMFTCaptureState state;
326
+ int sel;
327
+ uint8_t cpcfg;
328
+
329
+ /*
330
+ * If not mode 5, the behavior is undefined. We just do nothing in this
331
+ * case.
332
+ */
333
+ if (!(s->regs[R_NPCM7XX_MFT_MCTRL] & NPCM7XX_MFT_MCTRL_MODE5)) {
172
+ return;
334
+ return;
173
+ }
335
+ }
174
+
336
+
175
+ qdev_init_gpio_out(dev, s->out_irq, s->num_lines);
337
+ /* Capture input A. */
176
+}
338
+ if (s->regs[R_NPCM7XX_MFT_MCTRL] & NPCM7XX_MFT_MCTRL_TAEN &&
177
+
339
+ s->regs[R_NPCM7XX_MFT_CKC] & NPCM7XX_MFT_CKC_C1CSEL) {
178
+static Property split_irq_properties[] = {
340
+ sel = s->regs[R_NPCM7XX_MFT_INASEL] & NPCM7XX_MFT_INASEL_SELA;
179
+ DEFINE_PROP_UINT16("num-lines", SplitIRQ, num_lines, 1),
341
+ cpcfg = NPCM7XX_MFT_CPCFG_GET_A(s->regs[R_NPCM7XX_MFT_CPCFG]);
180
+ DEFINE_PROP_END_OF_LIST(),
342
+ state = npcm7xx_mft_compute_cnt(s->clock_1,
343
+ sel ? s->max_rpm[2] : s->max_rpm[0],
344
+ sel ? s->duty[2] : s->duty[0],
345
+ s->regs[R_NPCM7XX_MFT_CPA],
346
+ cpcfg,
347
+ &s->regs[R_NPCM7XX_MFT_CNT1]);
348
+ switch (state) {
349
+ case NPCM7XX_CAPTURE_SUCCEED:
350
+ /* Interrupt on input capture on TAn transition - TAPND */
351
+ s->regs[R_NPCM7XX_MFT_CRA] = s->regs[R_NPCM7XX_MFT_CNT1];
352
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TAPND;
353
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TAIEN) {
354
+ irq_level = 1;
355
+ }
356
+ break;
357
+
358
+ case NPCM7XX_CAPTURE_COMPARE_HIT:
359
+ /* Compare Hit - TEPND */
360
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TEPND;
361
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TEIEN) {
362
+ irq_level = 1;
363
+ }
364
+ break;
365
+
366
+ case NPCM7XX_CAPTURE_UNDERFLOW:
367
+ /* Underflow - TCPND */
368
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TCPND;
369
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TCIEN) {
370
+ irq_level = 1;
371
+ }
372
+ break;
373
+
374
+ default:
375
+ g_assert_not_reached();
376
+ }
377
+ }
378
+
379
+ /* Capture input B. */
380
+ if (s->regs[R_NPCM7XX_MFT_MCTRL] & NPCM7XX_MFT_MCTRL_TBEN &&
381
+ s->regs[R_NPCM7XX_MFT_CKC] & NPCM7XX_MFT_CKC_C2CSEL) {
382
+ sel = s->regs[R_NPCM7XX_MFT_INBSEL] & NPCM7XX_MFT_INBSEL_SELB;
383
+ cpcfg = NPCM7XX_MFT_CPCFG_GET_B(s->regs[R_NPCM7XX_MFT_CPCFG]);
384
+ state = npcm7xx_mft_compute_cnt(s->clock_2,
385
+ sel ? s->max_rpm[3] : s->max_rpm[1],
386
+ sel ? s->duty[3] : s->duty[1],
387
+ s->regs[R_NPCM7XX_MFT_CPB],
388
+ cpcfg,
389
+ &s->regs[R_NPCM7XX_MFT_CNT2]);
390
+ switch (state) {
391
+ case NPCM7XX_CAPTURE_SUCCEED:
392
+ /* Interrupt on input capture on TBn transition - TBPND */
393
+ s->regs[R_NPCM7XX_MFT_CRB] = s->regs[R_NPCM7XX_MFT_CNT2];
394
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TBPND;
395
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TBIEN) {
396
+ irq_level = 1;
397
+ }
398
+ break;
399
+
400
+ case NPCM7XX_CAPTURE_COMPARE_HIT:
401
+ /* Compare Hit - TFPND */
402
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TFPND;
403
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TFIEN) {
404
+ irq_level = 1;
405
+ }
406
+ break;
407
+
408
+ case NPCM7XX_CAPTURE_UNDERFLOW:
409
+ /* Underflow - TDPND */
410
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TDPND;
411
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TDIEN) {
412
+ irq_level = 1;
413
+ }
414
+ break;
415
+
416
+ default:
417
+ g_assert_not_reached();
418
+ }
419
+ }
420
+
421
+ trace_npcm7xx_mft_capture(DEVICE(s)->canonical_path, irq_level);
422
+ qemu_set_irq(s->irq, irq_level);
423
+}
424
+
425
+/* Update clock for counters. */
426
+static void npcm7xx_mft_update_clock(void *opaque, ClockEvent event)
427
+{
428
+ NPCM7xxMFTState *s = NPCM7XX_MFT(opaque);
429
+ uint64_t prescaled_clock_period;
430
+
431
+ prescaled_clock_period = clock_get(s->clock_in) *
432
+ (s->regs[R_NPCM7XX_MFT_PRSC] + 1ULL);
433
+ trace_npcm7xx_mft_update_clock(s->clock_in->canonical_path,
434
+ s->regs[R_NPCM7XX_MFT_CKC],
435
+ clock_get(s->clock_in),
436
+ prescaled_clock_period);
437
+ /* Update clock 1 */
438
+ if (s->regs[R_NPCM7XX_MFT_CKC] & NPCM7XX_MFT_CKC_C1CSEL) {
439
+ /* Clock is prescaled. */
440
+ clock_update(s->clock_1, prescaled_clock_period);
441
+ } else {
442
+ /* Clock stopped. */
443
+ clock_update(s->clock_1, 0);
444
+ }
445
+ /* Update clock 2 */
446
+ if (s->regs[R_NPCM7XX_MFT_CKC] & NPCM7XX_MFT_CKC_C2CSEL) {
447
+ /* Clock is prescaled. */
448
+ clock_update(s->clock_2, prescaled_clock_period);
449
+ } else {
450
+ /* Clock stopped. */
451
+ clock_update(s->clock_2, 0);
452
+ }
453
+
454
+ npcm7xx_mft_capture(s);
455
+}
456
+
457
+static uint64_t npcm7xx_mft_read(void *opaque, hwaddr offset, unsigned size)
458
+{
459
+ NPCM7xxMFTState *s = NPCM7XX_MFT(opaque);
460
+ uint16_t value = 0;
461
+
462
+ switch (offset) {
463
+ case A_NPCM7XX_MFT_ICLR:
464
+ qemu_log_mask(LOG_GUEST_ERROR,
465
+ "%s: register @ 0x%04" HWADDR_PRIx " is write-only\n",
466
+ __func__, offset);
467
+ break;
468
+
469
+ default:
470
+ value = s->regs[offset / 2];
471
+ }
472
+
473
+ trace_npcm7xx_mft_read(DEVICE(s)->canonical_path, offset, value);
474
+ return value;
475
+}
476
+
477
+static void npcm7xx_mft_write(void *opaque, hwaddr offset,
478
+ uint64_t v, unsigned size)
479
+{
480
+ NPCM7xxMFTState *s = NPCM7XX_MFT(opaque);
481
+
482
+ trace_npcm7xx_mft_write(DEVICE(s)->canonical_path, offset, v);
483
+ switch (offset) {
484
+ case A_NPCM7XX_MFT_ICLR:
485
+ npcm7xx_mft_clear_interrupt(s, v);
486
+ break;
487
+
488
+ case A_NPCM7XX_MFT_CKC:
489
+ case A_NPCM7XX_MFT_PRSC:
490
+ s->regs[offset / 2] = v;
491
+ npcm7xx_mft_update_clock(s, ClockUpdate);
492
+ break;
493
+
494
+ default:
495
+ s->regs[offset / 2] = v;
496
+ npcm7xx_mft_capture(s);
497
+ break;
498
+ }
499
+}
500
+
501
+static bool npcm7xx_mft_check_mem_op(void *opaque, hwaddr offset,
502
+ unsigned size, bool is_write,
503
+ MemTxAttrs attrs)
504
+{
505
+ switch (offset) {
506
+ /* 16-bit registers. Must be accessed with 16-bit read/write.*/
507
+ case A_NPCM7XX_MFT_CNT1:
508
+ case A_NPCM7XX_MFT_CRA:
509
+ case A_NPCM7XX_MFT_CRB:
510
+ case A_NPCM7XX_MFT_CNT2:
511
+ case A_NPCM7XX_MFT_CPA:
512
+ case A_NPCM7XX_MFT_CPB:
513
+ return size == 2;
514
+
515
+ /* 8-bit registers. Must be accessed with 8-bit read/write.*/
516
+ case A_NPCM7XX_MFT_PRSC:
517
+ case A_NPCM7XX_MFT_CKC:
518
+ case A_NPCM7XX_MFT_MCTRL:
519
+ case A_NPCM7XX_MFT_ICTRL:
520
+ case A_NPCM7XX_MFT_ICLR:
521
+ case A_NPCM7XX_MFT_IEN:
522
+ case A_NPCM7XX_MFT_CPCFG:
523
+ case A_NPCM7XX_MFT_INASEL:
524
+ case A_NPCM7XX_MFT_INBSEL:
525
+ return size == 1;
526
+
527
+ default:
528
+ /* Invalid registers. */
529
+ return false;
530
+ }
531
+}
532
+
533
+static void npcm7xx_mft_get_max_rpm(Object *obj, Visitor *v, const char *name,
534
+ void *opaque, Error **errp)
535
+{
536
+ visit_type_uint32(v, name, (uint32_t *)opaque, errp);
537
+}
538
+
539
+static void npcm7xx_mft_set_max_rpm(Object *obj, Visitor *v, const char *name,
540
+ void *opaque, Error **errp)
541
+{
542
+ NPCM7xxMFTState *s = NPCM7XX_MFT(obj);
543
+ uint32_t *max_rpm = opaque;
544
+ uint32_t value;
545
+
546
+ if (!visit_type_uint32(v, name, &value, errp)) {
547
+ return;
548
+ }
549
+
550
+ *max_rpm = value;
551
+ npcm7xx_mft_capture(s);
552
+}
553
+
554
+static void npcm7xx_mft_duty_handler(void *opaque, int n, int value)
555
+{
556
+ NPCM7xxMFTState *s = NPCM7XX_MFT(opaque);
557
+
558
+ trace_npcm7xx_mft_set_duty(DEVICE(s)->canonical_path, n, value);
559
+ s->duty[n] = value;
560
+ npcm7xx_mft_capture(s);
561
+}
562
+
563
+static const struct MemoryRegionOps npcm7xx_mft_ops = {
564
+ .read = npcm7xx_mft_read,
565
+ .write = npcm7xx_mft_write,
566
+ .endianness = DEVICE_LITTLE_ENDIAN,
567
+ .valid = {
568
+ .min_access_size = 1,
569
+ .max_access_size = 2,
570
+ .unaligned = false,
571
+ .accepts = npcm7xx_mft_check_mem_op,
572
+ },
181
+};
573
+};
182
+
574
+
183
+static void split_irq_class_init(ObjectClass *klass, void *data)
575
+static void npcm7xx_mft_enter_reset(Object *obj, ResetType type)
184
+{
576
+{
577
+ NPCM7xxMFTState *s = NPCM7XX_MFT(obj);
578
+
579
+ npcm7xx_mft_reset(s);
580
+}
581
+
582
+static void npcm7xx_mft_hold_reset(Object *obj)
583
+{
584
+ NPCM7xxMFTState *s = NPCM7XX_MFT(obj);
585
+
586
+ qemu_irq_lower(s->irq);
587
+}
588
+
589
+static void npcm7xx_mft_init(Object *obj)
590
+{
591
+ NPCM7xxMFTState *s = NPCM7XX_MFT(obj);
592
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
593
+ DeviceState *dev = DEVICE(obj);
594
+
595
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_mft_ops, s,
596
+ TYPE_NPCM7XX_MFT, 4 * KiB);
597
+ sysbus_init_mmio(sbd, &s->iomem);
598
+ sysbus_init_irq(sbd, &s->irq);
599
+ s->clock_in = qdev_init_clock_in(dev, "clock-in", npcm7xx_mft_update_clock,
600
+ s, ClockUpdate);
601
+ s->clock_1 = qdev_init_clock_out(dev, "clock1");
602
+ s->clock_2 = qdev_init_clock_out(dev, "clock2");
603
+
604
+ for (int i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
605
+ object_property_add(obj, "max_rpm[*]", "uint32",
606
+ npcm7xx_mft_get_max_rpm,
607
+ npcm7xx_mft_set_max_rpm,
608
+ NULL, &s->max_rpm[i]);
609
+ }
610
+ qdev_init_gpio_in_named(dev, npcm7xx_mft_duty_handler, "duty",
611
+ NPCM7XX_MFT_FANIN_COUNT);
612
+}
613
+
614
+static const VMStateDescription vmstate_npcm7xx_mft = {
615
+ .name = "npcm7xx-mft-module",
616
+ .version_id = 0,
617
+ .minimum_version_id = 0,
618
+ .fields = (VMStateField[]) {
619
+ VMSTATE_CLOCK(clock_in, NPCM7xxMFTState),
620
+ VMSTATE_CLOCK(clock_1, NPCM7xxMFTState),
621
+ VMSTATE_CLOCK(clock_2, NPCM7xxMFTState),
622
+ VMSTATE_UINT16_ARRAY(regs, NPCM7xxMFTState, NPCM7XX_MFT_NR_REGS),
623
+ VMSTATE_UINT32_ARRAY(max_rpm, NPCM7xxMFTState, NPCM7XX_MFT_FANIN_COUNT),
624
+ VMSTATE_UINT32_ARRAY(duty, NPCM7xxMFTState, NPCM7XX_MFT_FANIN_COUNT),
625
+ VMSTATE_END_OF_LIST(),
626
+ },
627
+};
628
+
629
+static void npcm7xx_mft_class_init(ObjectClass *klass, void *data)
630
+{
631
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
185
+ DeviceClass *dc = DEVICE_CLASS(klass);
632
+ DeviceClass *dc = DEVICE_CLASS(klass);
186
+
633
+
187
+ /* No state to reset or migrate */
634
+ dc->desc = "NPCM7xx MFT Controller";
188
+ dc->props = split_irq_properties;
635
+ dc->vmsd = &vmstate_npcm7xx_mft;
189
+ dc->realize = split_irq_realize;
636
+ rc->phases.enter = npcm7xx_mft_enter_reset;
190
+
637
+ rc->phases.hold = npcm7xx_mft_hold_reset;
191
+ /* Reason: Needs to be wired up to work */
638
+}
192
+ dc->user_creatable = false;
639
+
193
+}
640
+static const TypeInfo npcm7xx_mft_info = {
194
+
641
+ .name = TYPE_NPCM7XX_MFT,
195
+static const TypeInfo split_irq_type_info = {
642
+ .parent = TYPE_SYS_BUS_DEVICE,
196
+ .name = TYPE_SPLIT_IRQ,
643
+ .instance_size = sizeof(NPCM7xxMFTState),
197
+ .parent = TYPE_DEVICE,
644
+ .class_init = npcm7xx_mft_class_init,
198
+ .instance_size = sizeof(SplitIRQ),
645
+ .instance_init = npcm7xx_mft_init,
199
+ .instance_init = split_irq_init,
200
+ .class_init = split_irq_class_init,
201
+};
646
+};
202
+
647
+
203
+static void split_irq_register_types(void)
648
+static void npcm7xx_mft_register_type(void)
204
+{
649
+{
205
+ type_register_static(&split_irq_type_info);
650
+ type_register_static(&npcm7xx_mft_info);
206
+}
651
+}
207
+
652
+type_init(npcm7xx_mft_register_type);
208
+type_init(split_irq_register_types)
653
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
654
index XXXXXXX..XXXXXXX 100644
655
--- a/hw/misc/meson.build
656
+++ b/hw/misc/meson.build
657
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
658
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
659
'npcm7xx_clk.c',
660
'npcm7xx_gcr.c',
661
+ 'npcm7xx_mft.c',
662
'npcm7xx_pwm.c',
663
'npcm7xx_rng.c',
664
))
665
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
666
index XXXXXXX..XXXXXXX 100644
667
--- a/hw/misc/trace-events
668
+++ b/hw/misc/trace-events
669
@@ -XXX,XX +XXX,XX @@ npcm7xx_clk_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " valu
670
npcm7xx_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
671
npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
672
673
+# npcm7xx_mft.c
674
+npcm7xx_mft_read(const char *name, uint64_t offset, uint16_t value) "%s: offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
675
+npcm7xx_mft_write(const char *name, uint64_t offset, uint16_t value) "%s: offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
676
+npcm7xx_mft_rpm(const char *clock, uint32_t clock_hz, int state, int32_t cnt, uint32_t rpm, uint32_t duty) " fan clk: %s clock_hz: %" PRIu32 ", state: %d, cnt: %" PRIi32 ", rpm: %" PRIu32 ", duty: %" PRIu32
677
+npcm7xx_mft_capture(const char *name, int irq_level) "%s: level: %d"
678
+npcm7xx_mft_update_clock(const char *name, uint16_t sel, uint64_t clock_period, uint64_t prescaled_clock_period) "%s: sel: 0x%02" PRIx16 ", period: %" PRIu64 ", prescaled: %" PRIu64
679
+npcm7xx_mft_set_duty(const char *name, int n, int value) "%s[%d]: %d"
680
+
681
# npcm7xx_rng.c
682
npcm7xx_rng_read(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
683
npcm7xx_rng_write(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
209
--
684
--
210
2.16.2
685
2.20.1
211
686
212
687
diff view generated by jsdifflib
1
The Arm IoT Kit includes a "security controller" which is largely a
1
From: Hao Wu <wuhaotsh@google.com>
2
collection of registers for controlling the PPCs and other bits of
3
glue in the system. This commit provides the initial skeleton of the
4
device, implementing just the ID registers, and a couple of read-only
5
read-as-zero registers.
6
2
3
This patch adds the recently implemented MFT device to the NPCM7XX
4
SoC file.
5
6
Reviewed-by: Doug Evans <dje@google.com>
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
9
Message-id: 20210311180855.149764-4-wuhaotsh@google.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180220180325.29818-16-peter.maydell@linaro.org
10
---
12
---
11
hw/misc/Makefile.objs | 1 +
13
docs/system/arm/nuvoton.rst | 2 +-
12
include/hw/misc/iotkit-secctl.h | 39 ++++
14
include/hw/arm/npcm7xx.h | 2 ++
13
hw/misc/iotkit-secctl.c | 448 ++++++++++++++++++++++++++++++++++++++++
15
hw/arm/npcm7xx.c | 45 ++++++++++++++++++++++++++++++-------
14
default-configs/arm-softmmu.mak | 1 +
16
3 files changed, 40 insertions(+), 9 deletions(-)
15
hw/misc/trace-events | 7 +
16
5 files changed, 496 insertions(+)
17
create mode 100644 include/hw/misc/iotkit-secctl.h
18
create mode 100644 hw/misc/iotkit-secctl.c
19
17
20
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
18
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
21
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/Makefile.objs
20
--- a/docs/system/arm/nuvoton.rst
23
+++ b/hw/misc/Makefile.objs
21
+++ b/docs/system/arm/nuvoton.rst
24
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
22
@@ -XXX,XX +XXX,XX @@ Supported devices
25
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
23
* Pulse Width Modulation (PWM)
26
24
* SMBus controller (SMBF)
27
obj-$(CONFIG_TZ_PPC) += tz-ppc.o
25
* Ethernet controller (EMC)
28
+obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
26
+ * Tachometer
29
27
30
obj-$(CONFIG_PVPANIC) += pvpanic.o
28
Missing devices
31
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
29
---------------
32
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
30
@@ -XXX,XX +XXX,XX @@ Missing devices
33
new file mode 100644
31
* Peripheral SPI controller (PSPI)
34
index XXXXXXX..XXXXXXX
32
* SD/MMC host
35
--- /dev/null
33
* PECI interface
36
+++ b/include/hw/misc/iotkit-secctl.h
34
- * Tachometer
35
* PCI and PCIe root complex and bridges
36
* VDM and MCTP support
37
* Serial I/O expansion
38
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/hw/arm/npcm7xx.h
41
+++ b/include/hw/arm/npcm7xx.h
37
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@
38
+/*
43
#include "hw/mem/npcm7xx_mc.h"
39
+ * ARM IoT Kit security controller
44
#include "hw/misc/npcm7xx_clk.h"
40
+ *
45
#include "hw/misc/npcm7xx_gcr.h"
41
+ * Copyright (c) 2018 Linaro Limited
46
+#include "hw/misc/npcm7xx_mft.h"
42
+ * Written by Peter Maydell
47
#include "hw/misc/npcm7xx_pwm.h"
43
+ *
48
#include "hw/misc/npcm7xx_rng.h"
44
+ * This program is free software; you can redistribute it and/or modify
49
#include "hw/net/npcm7xx_emc.h"
45
+ * it under the terms of the GNU General Public License version 2 or
50
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
46
+ * (at your option) any later version.
51
NPCM7xxTimerCtrlState tim[3];
47
+ */
52
NPCM7xxADCState adc;
48
+
53
NPCM7xxPWMState pwm[2];
49
+/* This is a model of the security controller which is part of the
54
+ NPCM7xxMFTState mft[8];
50
+ * Arm IoT Kit and documented in
55
NPCM7xxOTPState key_storage;
51
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
56
NPCM7xxOTPState fuse_array;
52
+ *
57
NPCM7xxMCState mc;
53
+ * QEMU interface:
58
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
54
+ * + sysbus MMIO region 0 is the "secure privilege control block" registers
59
index XXXXXXX..XXXXXXX 100644
55
+ * + sysbus MMIO region 1 is the "non-secure privilege control block" registers
60
--- a/hw/arm/npcm7xx.c
56
+ */
61
+++ b/hw/arm/npcm7xx.c
57
+
62
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
58
+#ifndef IOTKIT_SECCTL_H
63
NPCM7XX_SMBUS15_IRQ,
59
+#define IOTKIT_SECCTL_H
64
NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
60
+
65
NPCM7XX_PWM1_IRQ, /* PWM module 1 */
61
+#include "hw/sysbus.h"
66
+ NPCM7XX_MFT0_IRQ = 96, /* MFT module 0 */
62
+
67
+ NPCM7XX_MFT1_IRQ, /* MFT module 1 */
63
+#define TYPE_IOTKIT_SECCTL "iotkit-secctl"
68
+ NPCM7XX_MFT2_IRQ, /* MFT module 2 */
64
+#define IOTKIT_SECCTL(obj) OBJECT_CHECK(IoTKitSecCtl, (obj), TYPE_IOTKIT_SECCTL)
69
+ NPCM7XX_MFT3_IRQ, /* MFT module 3 */
65
+
70
+ NPCM7XX_MFT4_IRQ, /* MFT module 4 */
66
+typedef struct IoTKitSecCtl {
71
+ NPCM7XX_MFT5_IRQ, /* MFT module 5 */
67
+ /*< private >*/
72
+ NPCM7XX_MFT6_IRQ, /* MFT module 6 */
68
+ SysBusDevice parent_obj;
73
+ NPCM7XX_MFT7_IRQ, /* MFT module 7 */
69
+
74
NPCM7XX_EMC2RX_IRQ = 114,
70
+ /*< public >*/
75
NPCM7XX_EMC2TX_IRQ,
71
+
76
NPCM7XX_GPIO0_IRQ = 116,
72
+ MemoryRegion s_regs;
77
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_pwm_addr[] = {
73
+ MemoryRegion ns_regs;
78
0xf0104000,
74
+} IoTKitSecCtl;
79
};
75
+
80
76
+#endif
81
+/* Register base address for each MFT Module */
77
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
82
+static const hwaddr npcm7xx_mft_addr[] = {
78
new file mode 100644
83
+ 0xf0180000,
79
index XXXXXXX..XXXXXXX
84
+ 0xf0181000,
80
--- /dev/null
85
+ 0xf0182000,
81
+++ b/hw/misc/iotkit-secctl.c
86
+ 0xf0183000,
82
@@ -XXX,XX +XXX,XX @@
87
+ 0xf0184000,
83
+/*
88
+ 0xf0185000,
84
+ * Arm IoT Kit security controller
89
+ 0xf0186000,
85
+ *
90
+ 0xf0187000,
86
+ * Copyright (c) 2018 Linaro Limited
87
+ * Written by Peter Maydell
88
+ *
89
+ * This program is free software; you can redistribute it and/or modify
90
+ * it under the terms of the GNU General Public License version 2 or
91
+ * (at your option) any later version.
92
+ */
93
+
94
+#include "qemu/osdep.h"
95
+#include "qemu/log.h"
96
+#include "qapi/error.h"
97
+#include "trace.h"
98
+#include "hw/sysbus.h"
99
+#include "hw/registerfields.h"
100
+#include "hw/misc/iotkit-secctl.h"
101
+
102
+/* Registers in the secure privilege control block */
103
+REG32(SECRESPCFG, 0x10)
104
+REG32(NSCCFG, 0x14)
105
+REG32(SECMPCINTSTATUS, 0x1c)
106
+REG32(SECPPCINTSTAT, 0x20)
107
+REG32(SECPPCINTCLR, 0x24)
108
+REG32(SECPPCINTEN, 0x28)
109
+REG32(SECMSCINTSTAT, 0x30)
110
+REG32(SECMSCINTCLR, 0x34)
111
+REG32(SECMSCINTEN, 0x38)
112
+REG32(BRGINTSTAT, 0x40)
113
+REG32(BRGINTCLR, 0x44)
114
+REG32(BRGINTEN, 0x48)
115
+REG32(AHBNSPPC0, 0x50)
116
+REG32(AHBNSPPCEXP0, 0x60)
117
+REG32(AHBNSPPCEXP1, 0x64)
118
+REG32(AHBNSPPCEXP2, 0x68)
119
+REG32(AHBNSPPCEXP3, 0x6c)
120
+REG32(APBNSPPC0, 0x70)
121
+REG32(APBNSPPC1, 0x74)
122
+REG32(APBNSPPCEXP0, 0x80)
123
+REG32(APBNSPPCEXP1, 0x84)
124
+REG32(APBNSPPCEXP2, 0x88)
125
+REG32(APBNSPPCEXP3, 0x8c)
126
+REG32(AHBSPPPC0, 0x90)
127
+REG32(AHBSPPPCEXP0, 0xa0)
128
+REG32(AHBSPPPCEXP1, 0xa4)
129
+REG32(AHBSPPPCEXP2, 0xa8)
130
+REG32(AHBSPPPCEXP3, 0xac)
131
+REG32(APBSPPPC0, 0xb0)
132
+REG32(APBSPPPC1, 0xb4)
133
+REG32(APBSPPPCEXP0, 0xc0)
134
+REG32(APBSPPPCEXP1, 0xc4)
135
+REG32(APBSPPPCEXP2, 0xc8)
136
+REG32(APBSPPPCEXP3, 0xcc)
137
+REG32(NSMSCEXP, 0xd0)
138
+REG32(PID4, 0xfd0)
139
+REG32(PID5, 0xfd4)
140
+REG32(PID6, 0xfd8)
141
+REG32(PID7, 0xfdc)
142
+REG32(PID0, 0xfe0)
143
+REG32(PID1, 0xfe4)
144
+REG32(PID2, 0xfe8)
145
+REG32(PID3, 0xfec)
146
+REG32(CID0, 0xff0)
147
+REG32(CID1, 0xff4)
148
+REG32(CID2, 0xff8)
149
+REG32(CID3, 0xffc)
150
+
151
+/* Registers in the non-secure privilege control block */
152
+REG32(AHBNSPPPC0, 0x90)
153
+REG32(AHBNSPPPCEXP0, 0xa0)
154
+REG32(AHBNSPPPCEXP1, 0xa4)
155
+REG32(AHBNSPPPCEXP2, 0xa8)
156
+REG32(AHBNSPPPCEXP3, 0xac)
157
+REG32(APBNSPPPC0, 0xb0)
158
+REG32(APBNSPPPC1, 0xb4)
159
+REG32(APBNSPPPCEXP0, 0xc0)
160
+REG32(APBNSPPPCEXP1, 0xc4)
161
+REG32(APBNSPPPCEXP2, 0xc8)
162
+REG32(APBNSPPPCEXP3, 0xcc)
163
+/* PID and CID registers are also present in the NS block */
164
+
165
+static const uint8_t iotkit_secctl_s_idregs[] = {
166
+ 0x04, 0x00, 0x00, 0x00,
167
+ 0x52, 0xb8, 0x0b, 0x00,
168
+ 0x0d, 0xf0, 0x05, 0xb1,
169
+};
91
+};
170
+
92
+
171
+static const uint8_t iotkit_secctl_ns_idregs[] = {
93
/* Direct memory-mapped access to each SMBus Module. */
172
+ 0x04, 0x00, 0x00, 0x00,
94
static const hwaddr npcm7xx_smbus_addr[] = {
173
+ 0x53, 0xb8, 0x0b, 0x00,
95
0xf0080000,
174
+ 0x0d, 0xf0, 0x05, 0xb1,
96
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
175
+};
97
object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
176
+
98
}
177
+static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
99
178
+ uint64_t *pdata,
100
+ for (i = 0; i < ARRAY_SIZE(s->mft); i++) {
179
+ unsigned size, MemTxAttrs attrs)
101
+ object_initialize_child(obj, "mft[*]", &s->mft[i], TYPE_NPCM7XX_MFT);
180
+{
181
+ uint64_t r;
182
+ uint32_t offset = addr & ~0x3;
183
+
184
+ switch (offset) {
185
+ case A_AHBNSPPC0:
186
+ case A_AHBSPPPC0:
187
+ r = 0;
188
+ break;
189
+ case A_SECRESPCFG:
190
+ case A_NSCCFG:
191
+ case A_SECMPCINTSTATUS:
192
+ case A_SECPPCINTSTAT:
193
+ case A_SECPPCINTEN:
194
+ case A_SECMSCINTSTAT:
195
+ case A_SECMSCINTEN:
196
+ case A_BRGINTSTAT:
197
+ case A_BRGINTEN:
198
+ case A_AHBNSPPCEXP0:
199
+ case A_AHBNSPPCEXP1:
200
+ case A_AHBNSPPCEXP2:
201
+ case A_AHBNSPPCEXP3:
202
+ case A_APBNSPPC0:
203
+ case A_APBNSPPC1:
204
+ case A_APBNSPPCEXP0:
205
+ case A_APBNSPPCEXP1:
206
+ case A_APBNSPPCEXP2:
207
+ case A_APBNSPPCEXP3:
208
+ case A_AHBSPPPCEXP0:
209
+ case A_AHBSPPPCEXP1:
210
+ case A_AHBSPPPCEXP2:
211
+ case A_AHBSPPPCEXP3:
212
+ case A_APBSPPPC0:
213
+ case A_APBSPPPC1:
214
+ case A_APBSPPPCEXP0:
215
+ case A_APBSPPPCEXP1:
216
+ case A_APBSPPPCEXP2:
217
+ case A_APBSPPPCEXP3:
218
+ case A_NSMSCEXP:
219
+ qemu_log_mask(LOG_UNIMP,
220
+ "IoTKit SecCtl S block read: "
221
+ "unimplemented offset 0x%x\n", offset);
222
+ r = 0;
223
+ break;
224
+ case A_PID4:
225
+ case A_PID5:
226
+ case A_PID6:
227
+ case A_PID7:
228
+ case A_PID0:
229
+ case A_PID1:
230
+ case A_PID2:
231
+ case A_PID3:
232
+ case A_CID0:
233
+ case A_CID1:
234
+ case A_CID2:
235
+ case A_CID3:
236
+ r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
237
+ break;
238
+ case A_SECPPCINTCLR:
239
+ case A_SECMSCINTCLR:
240
+ case A_BRGINTCLR:
241
+ qemu_log_mask(LOG_GUEST_ERROR,
242
+ "IotKit SecCtl S block read: write-only offset 0x%x\n",
243
+ offset);
244
+ r = 0;
245
+ break;
246
+ default:
247
+ qemu_log_mask(LOG_GUEST_ERROR,
248
+ "IotKit SecCtl S block read: bad offset 0x%x\n", offset);
249
+ r = 0;
250
+ break;
251
+ }
102
+ }
252
+
103
+
253
+ if (size != 4) {
104
for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
254
+ /* None of our registers are access-sensitive, so just pull the right
105
object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC);
255
+ * byte out of the word read result.
106
}
256
+ */
107
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
257
+ r = extract32(r, (addr & 3) * 8, size * 8);
108
sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
109
}
110
111
+ /* MFT Modules. Cannot fail. */
112
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_mft_addr) != ARRAY_SIZE(s->mft));
113
+ for (i = 0; i < ARRAY_SIZE(s->mft); i++) {
114
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->mft[i]);
115
+
116
+ qdev_connect_clock_in(DEVICE(&s->mft[i]), "clock-in",
117
+ qdev_get_clock_out(DEVICE(&s->clk),
118
+ "apb4-clock"));
119
+ sysbus_realize(sbd, &error_abort);
120
+ sysbus_mmio_map(sbd, 0, npcm7xx_mft_addr[i]);
121
+ sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, NPCM7XX_MFT0_IRQ + i));
258
+ }
122
+ }
259
+
123
+
260
+ trace_iotkit_secctl_s_read(offset, r, size);
124
/*
261
+ *pdata = r;
125
* EMC Modules. Cannot fail.
262
+ return MEMTX_OK;
126
* The mapping of the device to its netdev backend works as follows:
263
+}
127
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
264
+
128
create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
265
+static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
129
create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
266
+ uint64_t value,
130
create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
267
+ unsigned size, MemTxAttrs attrs)
131
- create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB);
268
+{
132
- create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB);
269
+ uint32_t offset = addr;
133
- create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB);
270
+
134
- create_unimplemented_device("npcm7xx.mft[3]", 0xf0183000, 4 * KiB);
271
+ trace_iotkit_secctl_s_write(offset, value, size);
135
- create_unimplemented_device("npcm7xx.mft[4]", 0xf0184000, 4 * KiB);
272
+
136
- create_unimplemented_device("npcm7xx.mft[5]", 0xf0185000, 4 * KiB);
273
+ if (size != 4) {
137
- create_unimplemented_device("npcm7xx.mft[6]", 0xf0186000, 4 * KiB);
274
+ /* Byte and halfword writes are ignored */
138
- create_unimplemented_device("npcm7xx.mft[7]", 0xf0187000, 4 * KiB);
275
+ qemu_log_mask(LOG_GUEST_ERROR,
139
create_unimplemented_device("npcm7xx.pspi1", 0xf0200000, 4 * KiB);
276
+ "IotKit SecCtl S block write: bad size, ignored\n");
140
create_unimplemented_device("npcm7xx.pspi2", 0xf0201000, 4 * KiB);
277
+ return MEMTX_OK;
141
create_unimplemented_device("npcm7xx.ahbpci", 0xf0400000, 1 * MiB);
278
+ }
279
+
280
+ switch (offset) {
281
+ case A_SECRESPCFG:
282
+ case A_NSCCFG:
283
+ case A_SECPPCINTCLR:
284
+ case A_SECPPCINTEN:
285
+ case A_SECMSCINTCLR:
286
+ case A_SECMSCINTEN:
287
+ case A_BRGINTCLR:
288
+ case A_BRGINTEN:
289
+ case A_AHBNSPPCEXP0:
290
+ case A_AHBNSPPCEXP1:
291
+ case A_AHBNSPPCEXP2:
292
+ case A_AHBNSPPCEXP3:
293
+ case A_APBNSPPC0:
294
+ case A_APBNSPPC1:
295
+ case A_APBNSPPCEXP0:
296
+ case A_APBNSPPCEXP1:
297
+ case A_APBNSPPCEXP2:
298
+ case A_APBNSPPCEXP3:
299
+ case A_AHBSPPPCEXP0:
300
+ case A_AHBSPPPCEXP1:
301
+ case A_AHBSPPPCEXP2:
302
+ case A_AHBSPPPCEXP3:
303
+ case A_APBSPPPC0:
304
+ case A_APBSPPPC1:
305
+ case A_APBSPPPCEXP0:
306
+ case A_APBSPPPCEXP1:
307
+ case A_APBSPPPCEXP2:
308
+ case A_APBSPPPCEXP3:
309
+ qemu_log_mask(LOG_UNIMP,
310
+ "IoTKit SecCtl S block write: "
311
+ "unimplemented offset 0x%x\n", offset);
312
+ break;
313
+ case A_SECMPCINTSTATUS:
314
+ case A_SECPPCINTSTAT:
315
+ case A_SECMSCINTSTAT:
316
+ case A_BRGINTSTAT:
317
+ case A_AHBNSPPC0:
318
+ case A_AHBSPPPC0:
319
+ case A_NSMSCEXP:
320
+ case A_PID4:
321
+ case A_PID5:
322
+ case A_PID6:
323
+ case A_PID7:
324
+ case A_PID0:
325
+ case A_PID1:
326
+ case A_PID2:
327
+ case A_PID3:
328
+ case A_CID0:
329
+ case A_CID1:
330
+ case A_CID2:
331
+ case A_CID3:
332
+ qemu_log_mask(LOG_GUEST_ERROR,
333
+ "IoTKit SecCtl S block write: "
334
+ "read-only offset 0x%x\n", offset);
335
+ break;
336
+ default:
337
+ qemu_log_mask(LOG_GUEST_ERROR,
338
+ "IotKit SecCtl S block write: bad offset 0x%x\n",
339
+ offset);
340
+ break;
341
+ }
342
+
343
+ return MEMTX_OK;
344
+}
345
+
346
+static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
347
+ uint64_t *pdata,
348
+ unsigned size, MemTxAttrs attrs)
349
+{
350
+ uint64_t r;
351
+ uint32_t offset = addr & ~0x3;
352
+
353
+ switch (offset) {
354
+ case A_AHBNSPPPC0:
355
+ r = 0;
356
+ break;
357
+ case A_AHBNSPPPCEXP0:
358
+ case A_AHBNSPPPCEXP1:
359
+ case A_AHBNSPPPCEXP2:
360
+ case A_AHBNSPPPCEXP3:
361
+ case A_APBNSPPPC0:
362
+ case A_APBNSPPPC1:
363
+ case A_APBNSPPPCEXP0:
364
+ case A_APBNSPPPCEXP1:
365
+ case A_APBNSPPPCEXP2:
366
+ case A_APBNSPPPCEXP3:
367
+ qemu_log_mask(LOG_UNIMP,
368
+ "IoTKit SecCtl NS block read: "
369
+ "unimplemented offset 0x%x\n", offset);
370
+ break;
371
+ case A_PID4:
372
+ case A_PID5:
373
+ case A_PID6:
374
+ case A_PID7:
375
+ case A_PID0:
376
+ case A_PID1:
377
+ case A_PID2:
378
+ case A_PID3:
379
+ case A_CID0:
380
+ case A_CID1:
381
+ case A_CID2:
382
+ case A_CID3:
383
+ r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
384
+ break;
385
+ default:
386
+ qemu_log_mask(LOG_GUEST_ERROR,
387
+ "IotKit SecCtl NS block write: bad offset 0x%x\n",
388
+ offset);
389
+ r = 0;
390
+ break;
391
+ }
392
+
393
+ if (size != 4) {
394
+ /* None of our registers are access-sensitive, so just pull the right
395
+ * byte out of the word read result.
396
+ */
397
+ r = extract32(r, (addr & 3) * 8, size * 8);
398
+ }
399
+
400
+ trace_iotkit_secctl_ns_read(offset, r, size);
401
+ *pdata = r;
402
+ return MEMTX_OK;
403
+}
404
+
405
+static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
406
+ uint64_t value,
407
+ unsigned size, MemTxAttrs attrs)
408
+{
409
+ uint32_t offset = addr;
410
+
411
+ trace_iotkit_secctl_ns_write(offset, value, size);
412
+
413
+ if (size != 4) {
414
+ /* Byte and halfword writes are ignored */
415
+ qemu_log_mask(LOG_GUEST_ERROR,
416
+ "IotKit SecCtl NS block write: bad size, ignored\n");
417
+ return MEMTX_OK;
418
+ }
419
+
420
+ switch (offset) {
421
+ case A_AHBNSPPPCEXP0:
422
+ case A_AHBNSPPPCEXP1:
423
+ case A_AHBNSPPPCEXP2:
424
+ case A_AHBNSPPPCEXP3:
425
+ case A_APBNSPPPC0:
426
+ case A_APBNSPPPC1:
427
+ case A_APBNSPPPCEXP0:
428
+ case A_APBNSPPPCEXP1:
429
+ case A_APBNSPPPCEXP2:
430
+ case A_APBNSPPPCEXP3:
431
+ qemu_log_mask(LOG_UNIMP,
432
+ "IoTKit SecCtl NS block write: "
433
+ "unimplemented offset 0x%x\n", offset);
434
+ break;
435
+ case A_AHBNSPPPC0:
436
+ case A_PID4:
437
+ case A_PID5:
438
+ case A_PID6:
439
+ case A_PID7:
440
+ case A_PID0:
441
+ case A_PID1:
442
+ case A_PID2:
443
+ case A_PID3:
444
+ case A_CID0:
445
+ case A_CID1:
446
+ case A_CID2:
447
+ case A_CID3:
448
+ qemu_log_mask(LOG_GUEST_ERROR,
449
+ "IoTKit SecCtl NS block write: "
450
+ "read-only offset 0x%x\n", offset);
451
+ break;
452
+ default:
453
+ qemu_log_mask(LOG_GUEST_ERROR,
454
+ "IotKit SecCtl NS block write: bad offset 0x%x\n",
455
+ offset);
456
+ break;
457
+ }
458
+
459
+ return MEMTX_OK;
460
+}
461
+
462
+static const MemoryRegionOps iotkit_secctl_s_ops = {
463
+ .read_with_attrs = iotkit_secctl_s_read,
464
+ .write_with_attrs = iotkit_secctl_s_write,
465
+ .endianness = DEVICE_LITTLE_ENDIAN,
466
+ .valid.min_access_size = 1,
467
+ .valid.max_access_size = 4,
468
+ .impl.min_access_size = 1,
469
+ .impl.max_access_size = 4,
470
+};
471
+
472
+static const MemoryRegionOps iotkit_secctl_ns_ops = {
473
+ .read_with_attrs = iotkit_secctl_ns_read,
474
+ .write_with_attrs = iotkit_secctl_ns_write,
475
+ .endianness = DEVICE_LITTLE_ENDIAN,
476
+ .valid.min_access_size = 1,
477
+ .valid.max_access_size = 4,
478
+ .impl.min_access_size = 1,
479
+ .impl.max_access_size = 4,
480
+};
481
+
482
+static void iotkit_secctl_reset(DeviceState *dev)
483
+{
484
+
485
+}
486
+
487
+static void iotkit_secctl_init(Object *obj)
488
+{
489
+ IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
490
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
491
+
492
+ memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
493
+ s, "iotkit-secctl-s-regs", 0x1000);
494
+ memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
495
+ s, "iotkit-secctl-ns-regs", 0x1000);
496
+ sysbus_init_mmio(sbd, &s->s_regs);
497
+ sysbus_init_mmio(sbd, &s->ns_regs);
498
+}
499
+
500
+static const VMStateDescription iotkit_secctl_vmstate = {
501
+ .name = "iotkit-secctl",
502
+ .version_id = 1,
503
+ .minimum_version_id = 1,
504
+ .fields = (VMStateField[]) {
505
+ VMSTATE_END_OF_LIST()
506
+ }
507
+};
508
+
509
+static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
510
+{
511
+ DeviceClass *dc = DEVICE_CLASS(klass);
512
+
513
+ dc->vmsd = &iotkit_secctl_vmstate;
514
+ dc->reset = iotkit_secctl_reset;
515
+}
516
+
517
+static const TypeInfo iotkit_secctl_info = {
518
+ .name = TYPE_IOTKIT_SECCTL,
519
+ .parent = TYPE_SYS_BUS_DEVICE,
520
+ .instance_size = sizeof(IoTKitSecCtl),
521
+ .instance_init = iotkit_secctl_init,
522
+ .class_init = iotkit_secctl_class_init,
523
+};
524
+
525
+static void iotkit_secctl_register_types(void)
526
+{
527
+ type_register_static(&iotkit_secctl_info);
528
+}
529
+
530
+type_init(iotkit_secctl_register_types);
531
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
532
index XXXXXXX..XXXXXXX 100644
533
--- a/default-configs/arm-softmmu.mak
534
+++ b/default-configs/arm-softmmu.mak
535
@@ -XXX,XX +XXX,XX @@ CONFIG_MPS2_FPGAIO=y
536
CONFIG_MPS2_SCC=y
537
538
CONFIG_TZ_PPC=y
539
+CONFIG_IOTKIT_SECCTL=y
540
541
CONFIG_VERSATILE_PCI=y
542
CONFIG_VERSATILE_I2C=y
543
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
544
index XXXXXXX..XXXXXXX 100644
545
--- a/hw/misc/trace-events
546
+++ b/hw/misc/trace-events
547
@@ -XXX,XX +XXX,XX @@ tz_ppc_irq_clear(int level) "TZ PPC: int_clear = %d"
548
tz_ppc_update_irq(int level) "TZ PPC: setting irq line to %d"
549
tz_ppc_read_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " read (secure %d user %d) blocked"
550
tz_ppc_write_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " write (secure %d user %d) blocked"
551
+
552
+# hw/misc/iotkit-secctl.c
553
+iotkit_secctl_s_read(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl S regs read: offset 0x%x data 0x%" PRIx64 " size %u"
554
+iotkit_secctl_s_write(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl S regs write: offset 0x%x data 0x%" PRIx64 " size %u"
555
+iotkit_secctl_ns_read(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl NS regs read: offset 0x%x data 0x%" PRIx64 " size %u"
556
+iotkit_secctl_ns_write(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl NS regs write: offset 0x%x data 0x%" PRIx64 " size %u"
557
+iotkit_secctl_reset(void) "IoTKit SecCtl: reset"
558
--
142
--
559
2.16.2
143
2.20.1
560
144
561
145
diff view generated by jsdifflib
1
Create an "idau" property on the armv7m container object which
1
From: Hao Wu <wuhaotsh@google.com>
2
we can forward to the CPU object. Annoyingly, we can't use
2
3
object_property_add_alias() because the CPU object we want to
3
This patch adds fan_splitters (split IRQs) in NPCM7XX boards. Each fan
4
forward to doesn't exist until the armv7m container is realized.
4
splitter corresponds to 1 PWM output and can connect to multiple fan
5
5
inputs (MFT devices).
6
In NPCM7XX boards(NPCM750 EVB and Quanta GSJ boards), we initializes
7
these splitters and connect them to their corresponding modules
8
according their specific device trees.
9
10
Reviewed-by: Doug Evans <dje@google.com>
11
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
12
Signed-off-by: Hao Wu <wuhaotsh@google.com>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20210311180855.149764-5-wuhaotsh@google.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-6-peter.maydell@linaro.org
9
---
16
---
10
include/hw/arm/armv7m.h | 3 +++
17
include/hw/arm/npcm7xx.h | 11 ++++-
11
hw/arm/armv7m.c | 9 +++++++++
18
hw/arm/npcm7xx_boards.c | 99 ++++++++++++++++++++++++++++++++++++++++
12
2 files changed, 12 insertions(+)
19
2 files changed, 109 insertions(+), 1 deletion(-)
13
20
14
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
21
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
15
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/armv7m.h
23
--- a/include/hw/arm/npcm7xx.h
17
+++ b/include/hw/arm/armv7m.h
24
+++ b/include/hw/arm/npcm7xx.h
18
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@
19
26
20
#include "hw/sysbus.h"
27
#include "hw/boards.h"
21
#include "hw/intc/armv7m_nvic.h"
28
#include "hw/adc/npcm7xx_adc.h"
22
+#include "target/arm/idau.h"
29
+#include "hw/core/split-irq.h"
23
30
#include "hw/cpu/a9mpcore.h"
24
#define TYPE_BITBAND "ARM,bitband-memory"
31
#include "hw/gpio/npcm7xx_gpio.h"
25
#define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
32
#include "hw/i2c/npcm7xx_smbus.h"
26
@@ -XXX,XX +XXX,XX @@ typedef struct {
33
@@ -XXX,XX +XXX,XX @@
27
* + Property "memory": MemoryRegion defining the physical address space
34
#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
28
* that CPU accesses see. (The NVIC, bitbanding and other CPU-internal
35
#define NPCM7XX_BOARD_SETUP_ADDR (0xffff1000) /* Boot ROM */
29
* devices will be automatically layered on top of this view.)
36
30
+ * + Property "idau": IDAU interface (forwarded to CPU object)
37
+#define NPCM7XX_NR_PWM_MODULES 2
31
*/
38
+
32
typedef struct ARMv7MState {
39
typedef struct NPCM7xxMachine {
33
/*< private >*/
40
MachineState parent;
34
@@ -XXX,XX +XXX,XX @@ typedef struct ARMv7MState {
41
+ /*
35
char *cpu_type;
42
+ * PWM fan splitter. each splitter connects to one PWM output and
36
/* MemoryRegion the board provides to us (with its devices, RAM, etc) */
43
+ * multiple MFT inputs.
37
MemoryRegion *board_memory;
44
+ */
38
+ Object *idau;
45
+ SplitIRQ fan_splitter[NPCM7XX_NR_PWM_MODULES *
39
} ARMv7MState;
46
+ NPCM7XX_PWM_PER_MODULE];
40
47
} NPCM7xxMachine;
41
#endif
48
42
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
49
#define TYPE_NPCM7XX_MACHINE MACHINE_TYPE_NAME("npcm7xx")
50
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
51
NPCM7xxCLKState clk;
52
NPCM7xxTimerCtrlState tim[3];
53
NPCM7xxADCState adc;
54
- NPCM7xxPWMState pwm[2];
55
+ NPCM7xxPWMState pwm[NPCM7XX_NR_PWM_MODULES];
56
NPCM7xxMFTState mft[8];
57
NPCM7xxOTPState key_storage;
58
NPCM7xxOTPState fuse_array;
59
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
43
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/armv7m.c
61
--- a/hw/arm/npcm7xx_boards.c
45
+++ b/hw/arm/armv7m.c
62
+++ b/hw/arm/npcm7xx_boards.c
46
@@ -XXX,XX +XXX,XX @@
63
@@ -XXX,XX +XXX,XX @@
47
#include "sysemu/qtest.h"
64
#include "hw/core/cpu.h"
48
#include "qemu/error-report.h"
65
#include "hw/i2c/smbus_eeprom.h"
49
#include "exec/address-spaces.h"
66
#include "hw/loader.h"
50
+#include "target/arm/idau.h"
67
+#include "hw/qdev-core.h"
51
68
#include "hw/qdev-properties.h"
52
/* Bitbanded IO. Each word corresponds to a single bit. */
69
#include "qapi/error.h"
53
70
#include "qemu-common.h"
54
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
71
@@ -XXX,XX +XXX,XX @@ static void at24c_eeprom_init(NPCM7xxState *soc, int bus, uint8_t addr,
55
72
i2c_slave_realize_and_unref(i2c_dev, i2c_bus, &error_abort);
56
object_property_set_link(OBJECT(s->cpu), OBJECT(&s->container), "memory",
73
}
57
&error_abort);
74
58
+ if (object_property_find(OBJECT(s->cpu), "idau", NULL)) {
75
+static void npcm7xx_init_pwm_splitter(NPCM7xxMachine *machine,
59
+ object_property_set_link(OBJECT(s->cpu), s->idau, "idau", &err);
76
+ NPCM7xxState *soc, const int *fan_counts)
60
+ if (err != NULL) {
77
+{
61
+ error_propagate(errp, err);
78
+ SplitIRQ *splitters = machine->fan_splitter;
62
+ return;
79
+
80
+ /*
81
+ * PWM 0~3 belong to module 0 output 0~3.
82
+ * PWM 4~7 belong to module 1 output 0~3.
83
+ */
84
+ for (int i = 0; i < NPCM7XX_NR_PWM_MODULES; ++i) {
85
+ for (int j = 0; j < NPCM7XX_PWM_PER_MODULE; ++j) {
86
+ int splitter_no = i * NPCM7XX_PWM_PER_MODULE + j;
87
+ DeviceState *splitter;
88
+
89
+ if (fan_counts[splitter_no] < 1) {
90
+ continue;
91
+ }
92
+ object_initialize_child(OBJECT(machine), "fan-splitter[*]",
93
+ &splitters[splitter_no], TYPE_SPLIT_IRQ);
94
+ splitter = DEVICE(&splitters[splitter_no]);
95
+ qdev_prop_set_uint16(splitter, "num-lines",
96
+ fan_counts[splitter_no]);
97
+ qdev_realize(splitter, NULL, &error_abort);
98
+ qdev_connect_gpio_out_named(DEVICE(&soc->pwm[i]), "duty-gpio-out",
99
+ j, qdev_get_gpio_in(splitter, 0));
63
+ }
100
+ }
64
+ }
101
+ }
65
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
102
+}
66
if (err != NULL) {
103
+
67
error_propagate(errp, err);
104
+static void npcm7xx_connect_pwm_fan(NPCM7xxState *soc, SplitIRQ *splitter,
68
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
105
+ int fan_no, int output_no)
69
DEFINE_PROP_STRING("cpu-type", ARMv7MState, cpu_type),
106
+{
70
DEFINE_PROP_LINK("memory", ARMv7MState, board_memory, TYPE_MEMORY_REGION,
107
+ DeviceState *fan;
71
MemoryRegion *),
108
+ int fan_input;
72
+ DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
109
+ qemu_irq fan_duty_gpio;
73
DEFINE_PROP_END_OF_LIST(),
110
+
74
};
111
+ g_assert(fan_no >= 0 && fan_no <= NPCM7XX_MFT_MAX_FAN_INPUT);
112
+ /*
113
+ * Fan 0~1 belong to module 0 input 0~1.
114
+ * Fan 2~3 belong to module 1 input 0~1.
115
+ * ...
116
+ * Fan 14~15 belong to module 7 input 0~1.
117
+ * Fan 16~17 belong to module 0 input 2~3.
118
+ * Fan 18~19 belong to module 1 input 2~3.
119
+ */
120
+ if (fan_no < 16) {
121
+ fan = DEVICE(&soc->mft[fan_no / 2]);
122
+ fan_input = fan_no % 2;
123
+ } else {
124
+ fan = DEVICE(&soc->mft[(fan_no - 16) / 2]);
125
+ fan_input = fan_no % 2 + 2;
126
+ }
127
+
128
+ /* Connect the Fan to PWM module */
129
+ fan_duty_gpio = qdev_get_gpio_in_named(fan, "duty", fan_input);
130
+ qdev_connect_gpio_out(DEVICE(splitter), output_no, fan_duty_gpio);
131
+}
132
+
133
static void npcm750_evb_i2c_init(NPCM7xxState *soc)
134
{
135
/* lm75 temperature sensor on SVB, tmp105 is compatible */
136
@@ -XXX,XX +XXX,XX @@ static void npcm750_evb_i2c_init(NPCM7xxState *soc)
137
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 6), "tmp105", 0x48);
138
}
139
140
+static void npcm750_evb_fan_init(NPCM7xxMachine *machine, NPCM7xxState *soc)
141
+{
142
+ SplitIRQ *splitter = machine->fan_splitter;
143
+ static const int fan_counts[] = {2, 2, 2, 2, 2, 2, 2, 2};
144
+
145
+ npcm7xx_init_pwm_splitter(machine, soc, fan_counts);
146
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x00, 0);
147
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x01, 1);
148
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x02, 0);
149
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x03, 1);
150
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x04, 0);
151
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x05, 1);
152
+ npcm7xx_connect_pwm_fan(soc, &splitter[3], 0x06, 0);
153
+ npcm7xx_connect_pwm_fan(soc, &splitter[3], 0x07, 1);
154
+ npcm7xx_connect_pwm_fan(soc, &splitter[4], 0x08, 0);
155
+ npcm7xx_connect_pwm_fan(soc, &splitter[4], 0x09, 1);
156
+ npcm7xx_connect_pwm_fan(soc, &splitter[5], 0x0a, 0);
157
+ npcm7xx_connect_pwm_fan(soc, &splitter[5], 0x0b, 1);
158
+ npcm7xx_connect_pwm_fan(soc, &splitter[6], 0x0c, 0);
159
+ npcm7xx_connect_pwm_fan(soc, &splitter[6], 0x0d, 1);
160
+ npcm7xx_connect_pwm_fan(soc, &splitter[7], 0x0e, 0);
161
+ npcm7xx_connect_pwm_fan(soc, &splitter[7], 0x0f, 1);
162
+}
163
+
164
static void quanta_gsj_i2c_init(NPCM7xxState *soc)
165
{
166
/* GSJ machine have 4 max31725 temperature sensors, tmp105 is compatible. */
167
@@ -XXX,XX +XXX,XX @@ static void quanta_gsj_i2c_init(NPCM7xxState *soc)
168
/* TODO: Add additional i2c devices. */
169
}
170
171
+static void quanta_gsj_fan_init(NPCM7xxMachine *machine, NPCM7xxState *soc)
172
+{
173
+ SplitIRQ *splitter = machine->fan_splitter;
174
+ static const int fan_counts[] = {2, 2, 2, 0, 0, 0, 0, 0};
175
+
176
+ npcm7xx_init_pwm_splitter(machine, soc, fan_counts);
177
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x00, 0);
178
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x01, 1);
179
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x02, 0);
180
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x03, 1);
181
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x04, 0);
182
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x05, 1);
183
+}
184
+
185
static void npcm750_evb_init(MachineState *machine)
186
{
187
NPCM7xxState *soc;
188
@@ -XXX,XX +XXX,XX @@ static void npcm750_evb_init(MachineState *machine)
189
npcm7xx_load_bootrom(machine, soc);
190
npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", drive_get(IF_MTD, 0, 0));
191
npcm750_evb_i2c_init(soc);
192
+ npcm750_evb_fan_init(NPCM7XX_MACHINE(machine), soc);
193
npcm7xx_load_kernel(machine, soc);
194
}
195
196
@@ -XXX,XX +XXX,XX @@ static void quanta_gsj_init(MachineState *machine)
197
npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e",
198
drive_get(IF_MTD, 0, 0));
199
quanta_gsj_i2c_init(soc);
200
+ quanta_gsj_fan_init(NPCM7XX_MACHINE(machine), soc);
201
npcm7xx_load_kernel(machine, soc);
202
}
75
203
76
--
204
--
77
2.16.2
205
2.20.1
78
206
79
207
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
This patch adds testing of PWM fan RPMs in the existing npcm7xx pwm
4
test. It tests whether the MFT module can measure correct fan values
5
for a PWM fan in NPCM7XX boards.
6
7
Reviewed-by: Doug Evans <dje@google.com>
8
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
9
Signed-off-by: Hao Wu <wuhaotsh@google.com>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20180228193125.20577-14-richard.henderson@linaro.org
11
Message-id: 20210311180855.149764-6-wuhaotsh@google.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
13
---
8
target/arm/translate.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++
14
tests/qtest/npcm7xx_pwm-test.c | 205 ++++++++++++++++++++++++++++++++-
9
1 file changed, 68 insertions(+)
15
1 file changed, 199 insertions(+), 6 deletions(-)
10
16
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
19
--- a/tests/qtest/npcm7xx_pwm-test.c
14
+++ b/target/arm/translate.c
20
+++ b/tests/qtest/npcm7xx_pwm-test.c
15
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
21
@@ -XXX,XX +XXX,XX @@
16
return 0;
22
#define PLL_FBDV(rv) extract32((rv), 16, 12)
17
}
23
#define PLL_OTDV1(rv) extract32((rv), 8, 3)
18
24
#define PLL_OTDV2(rv) extract32((rv), 13, 3)
19
+/* Advanced SIMD three registers of the same length extension.
25
+#define APB4CKDIV(rv) extract32((rv), 30, 2)
20
+ * 31 25 23 22 20 16 12 11 10 9 8 3 0
26
#define APB3CKDIV(rv) extract32((rv), 28, 2)
21
+ * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
27
#define CLK2CKDIV(rv) extract32((rv), 0, 1)
22
+ * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
28
#define CLK4CKDIV(rv) extract32((rv), 26, 2)
23
+ * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
29
@@ -XXX,XX +XXX,XX @@
24
+ */
30
25
+static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
31
#define MAX_DUTY 1000000
26
+{
32
27
+ gen_helper_gvec_3_ptr *fn_gvec_ptr;
33
+/* MFT (PWM fan) related */
28
+ int rd, rn, rm, rot, size, opr_sz;
34
+#define MFT_BA(n) (0xf0180000 + ((n) * 0x1000))
29
+ TCGv_ptr fpst;
35
+#define MFT_IRQ(n) (96 + (n))
30
+ bool q;
36
+#define MFT_CNT1 0x00
31
+
37
+#define MFT_CRA 0x02
32
+ q = extract32(insn, 6, 1);
38
+#define MFT_CRB 0x04
33
+ VFP_DREG_D(rd, insn);
39
+#define MFT_CNT2 0x06
34
+ VFP_DREG_N(rn, insn);
40
+#define MFT_PRSC 0x08
35
+ VFP_DREG_M(rm, insn);
41
+#define MFT_CKC 0x0a
36
+ if ((rd | rn | rm) & q) {
42
+#define MFT_MCTRL 0x0c
37
+ return 1;
43
+#define MFT_ICTRL 0x0e
44
+#define MFT_ICLR 0x10
45
+#define MFT_IEN 0x12
46
+#define MFT_CPA 0x14
47
+#define MFT_CPB 0x16
48
+#define MFT_CPCFG 0x18
49
+#define MFT_INASEL 0x1a
50
+#define MFT_INBSEL 0x1c
51
+
52
+#define MFT_MCTRL_ALL 0x64
53
+#define MFT_ICLR_ALL 0x3f
54
+#define MFT_IEN_ALL 0x3f
55
+#define MFT_CPCFG_EQ_MODE 0x44
56
+
57
+#define MFT_CKC_C2CSEL BIT(3)
58
+#define MFT_CKC_C1CSEL BIT(0)
59
+
60
+#define MFT_ICTRL_TFPND BIT(5)
61
+#define MFT_ICTRL_TEPND BIT(4)
62
+#define MFT_ICTRL_TDPND BIT(3)
63
+#define MFT_ICTRL_TCPND BIT(2)
64
+#define MFT_ICTRL_TBPND BIT(1)
65
+#define MFT_ICTRL_TAPND BIT(0)
66
+
67
+#define MFT_MAX_CNT 0xffff
68
+#define MFT_TIMEOUT 0x5000
69
+
70
+#define DEFAULT_RPM 19800
71
+#define DEFAULT_PRSC 255
72
+#define MFT_PULSE_PER_REVOLUTION 2
73
+
74
+#define MAX_ERROR 1
75
+
76
typedef struct PWMModule {
77
int irq;
78
uint64_t base_addr;
79
@@ -XXX,XX +XXX,XX @@ static uint64_t pwm_get_duty(QTestState *qts, int module_index, int pwm_index)
80
return pwm_qom_get(qts, path, name);
81
}
82
83
+static void mft_qom_set(QTestState *qts, int index, const char *name,
84
+ uint32_t value)
85
+{
86
+ QDict *response;
87
+ char *path = g_strdup_printf("/machine/soc/mft[%d]", index);
88
+
89
+ g_test_message("Setting properties %s of mft[%d] with value %u",
90
+ name, index, value);
91
+ response = qtest_qmp(qts, "{ 'execute': 'qom-set',"
92
+ " 'arguments': { 'path': %s, "
93
+ " 'property': %s, 'value': %u}}",
94
+ path, name, value);
95
+ /* The qom set message returns successfully. */
96
+ g_assert_true(qdict_haskey(response, "return"));
97
+}
98
+
99
static uint32_t get_pll(uint32_t con)
100
{
101
return REF_HZ * PLL_FBDV(con) / (PLL_INDV(con) * PLL_OTDV1(con)
102
* PLL_OTDV2(con));
103
}
104
105
-static uint64_t read_pclk(QTestState *qts)
106
+static uint64_t read_pclk(QTestState *qts, bool mft)
107
{
108
uint64_t freq = REF_HZ;
109
uint32_t clksel = qtest_readl(qts, CLK_BA + CLKSEL);
110
uint32_t pllcon;
111
uint32_t clkdiv1 = qtest_readl(qts, CLK_BA + CLKDIV1);
112
uint32_t clkdiv2 = qtest_readl(qts, CLK_BA + CLKDIV2);
113
+ uint32_t apbdiv = mft ? APB4CKDIV(clkdiv2) : APB3CKDIV(clkdiv2);
114
115
switch (CPUCKSEL(clksel)) {
116
case 0:
117
@@ -XXX,XX +XXX,XX @@ static uint64_t read_pclk(QTestState *qts)
118
g_assert_not_reached();
119
}
120
121
- freq >>= (CLK2CKDIV(clkdiv1) + CLK4CKDIV(clkdiv1) + APB3CKDIV(clkdiv2));
122
+ freq >>= (CLK2CKDIV(clkdiv1) + CLK4CKDIV(clkdiv1) + apbdiv);
123
124
return freq;
125
}
126
@@ -XXX,XX +XXX,XX @@ static uint32_t pwm_selector(uint32_t csr)
127
static uint64_t pwm_compute_freq(QTestState *qts, uint32_t ppr, uint32_t csr,
128
uint32_t cnr)
129
{
130
- return read_pclk(qts) / ((ppr + 1) * pwm_selector(csr) * (cnr + 1));
131
+ return read_pclk(qts, false) / ((ppr + 1) * pwm_selector(csr) * (cnr + 1));
132
}
133
134
static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
135
@@ -XXX,XX +XXX,XX @@ static void pwm_write(QTestState *qts, const TestData *td, unsigned offset,
136
qtest_writel(qts, td->module->base_addr + offset, value);
137
}
138
139
+static uint8_t mft_readb(QTestState *qts, int index, unsigned offset)
140
+{
141
+ return qtest_readb(qts, MFT_BA(index) + offset);
142
+}
143
+
144
+static uint16_t mft_readw(QTestState *qts, int index, unsigned offset)
145
+{
146
+ return qtest_readw(qts, MFT_BA(index) + offset);
147
+}
148
+
149
+static void mft_writeb(QTestState *qts, int index, unsigned offset,
150
+ uint8_t value)
151
+{
152
+ qtest_writeb(qts, MFT_BA(index) + offset, value);
153
+}
154
+
155
+static void mft_writew(QTestState *qts, int index, unsigned offset,
156
+ uint16_t value)
157
+{
158
+ return qtest_writew(qts, MFT_BA(index) + offset, value);
159
+}
160
+
161
static uint32_t pwm_read_ppr(QTestState *qts, const TestData *td)
162
{
163
return extract32(pwm_read(qts, td, PPR), ppr_base[pwm_index(td->pwm)], 8);
164
@@ -XXX,XX +XXX,XX @@ static void pwm_write_cmr(QTestState *qts, const TestData *td, uint32_t value)
165
pwm_write(qts, td, td->pwm->cmr_offset, value);
166
}
167
168
+static int mft_compute_index(const TestData *td)
169
+{
170
+ int index = pwm_module_index(td->module) * ARRAY_SIZE(pwm_list) +
171
+ pwm_index(td->pwm);
172
+
173
+ g_assert_cmpint(index, <,
174
+ ARRAY_SIZE(pwm_module_list) * ARRAY_SIZE(pwm_list));
175
+
176
+ return index;
177
+}
178
+
179
+static void mft_reset_counters(QTestState *qts, int index)
180
+{
181
+ mft_writew(qts, index, MFT_CNT1, MFT_MAX_CNT);
182
+ mft_writew(qts, index, MFT_CNT2, MFT_MAX_CNT);
183
+ mft_writew(qts, index, MFT_CRA, MFT_MAX_CNT);
184
+ mft_writew(qts, index, MFT_CRB, MFT_MAX_CNT);
185
+ mft_writew(qts, index, MFT_CPA, MFT_MAX_CNT - MFT_TIMEOUT);
186
+ mft_writew(qts, index, MFT_CPB, MFT_MAX_CNT - MFT_TIMEOUT);
187
+}
188
+
189
+static void mft_init(QTestState *qts, const TestData *td)
190
+{
191
+ int index = mft_compute_index(td);
192
+
193
+ /* Enable everything */
194
+ mft_writeb(qts, index, MFT_CKC, 0);
195
+ mft_writeb(qts, index, MFT_ICLR, MFT_ICLR_ALL);
196
+ mft_writeb(qts, index, MFT_MCTRL, MFT_MCTRL_ALL);
197
+ mft_writeb(qts, index, MFT_IEN, MFT_IEN_ALL);
198
+ mft_writeb(qts, index, MFT_INASEL, 0);
199
+ mft_writeb(qts, index, MFT_INBSEL, 0);
200
+
201
+ /* Set cpcfg to use EQ mode, same as kernel driver */
202
+ mft_writeb(qts, index, MFT_CPCFG, MFT_CPCFG_EQ_MODE);
203
+
204
+ /* Write default counters, timeout and prescaler */
205
+ mft_reset_counters(qts, index);
206
+ mft_writeb(qts, index, MFT_PRSC, DEFAULT_PRSC);
207
+
208
+ /* Write default max rpm via QMP */
209
+ mft_qom_set(qts, index, "max_rpm[0]", DEFAULT_RPM);
210
+ mft_qom_set(qts, index, "max_rpm[1]", DEFAULT_RPM);
211
+}
212
+
213
+static int32_t mft_compute_cnt(uint32_t rpm, uint64_t clk)
214
+{
215
+ uint64_t cnt;
216
+
217
+ if (rpm == 0) {
218
+ return -1;
38
+ }
219
+ }
39
+
220
+
40
+ if ((insn & 0xfe200f10) == 0xfc200800) {
221
+ cnt = clk * 60 / ((DEFAULT_PRSC + 1) * rpm * MFT_PULSE_PER_REVOLUTION);
41
+ /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
222
+ if (cnt >= MFT_TIMEOUT) {
42
+ size = extract32(insn, 20, 1);
223
+ return -1;
43
+ rot = extract32(insn, 23, 2);
224
+ }
44
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
225
+ return MFT_MAX_CNT - cnt;
45
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
226
+}
46
+ return 1;
227
+
47
+ }
228
+static void mft_verify_rpm(QTestState *qts, const TestData *td, uint64_t duty)
48
+ fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
229
+{
49
+ } else if ((insn & 0xfea00f10) == 0xfc800800) {
230
+ int index = mft_compute_index(td);
50
+ /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
231
+ uint16_t cnt, cr;
51
+ size = extract32(insn, 20, 1);
232
+ uint32_t rpm = DEFAULT_RPM * duty / MAX_DUTY;
52
+ rot = extract32(insn, 24, 1);
233
+ uint64_t clk = read_pclk(qts, true);
53
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
234
+ int32_t expected_cnt = mft_compute_cnt(rpm, clk);
54
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
235
+
55
+ return 1;
236
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
56
+ }
237
+ g_test_message(
57
+ fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
238
+ "verifying rpm for mft[%d]: clk: %lu, duty: %lu, rpm: %u, cnt: %d",
239
+ index, clk, duty, rpm, expected_cnt);
240
+
241
+ /* Verify rpm for fan A */
242
+ /* Stop capture */
243
+ mft_writeb(qts, index, MFT_CKC, 0);
244
+ mft_writeb(qts, index, MFT_ICLR, MFT_ICLR_ALL);
245
+ mft_reset_counters(qts, index);
246
+ g_assert_cmphex(mft_readw(qts, index, MFT_CNT1), ==, MFT_MAX_CNT);
247
+ g_assert_cmphex(mft_readw(qts, index, MFT_CRA), ==, MFT_MAX_CNT);
248
+ g_assert_cmphex(mft_readw(qts, index, MFT_CPA), ==,
249
+ MFT_MAX_CNT - MFT_TIMEOUT);
250
+ /* Start capture */
251
+ mft_writeb(qts, index, MFT_CKC, MFT_CKC_C1CSEL);
252
+ g_assert_true(qtest_get_irq(qts, MFT_IRQ(index)));
253
+ if (expected_cnt == -1) {
254
+ g_assert_cmphex(mft_readb(qts, index, MFT_ICTRL), ==, MFT_ICTRL_TEPND);
58
+ } else {
255
+ } else {
59
+ return 1;
256
+ g_assert_cmphex(mft_readb(qts, index, MFT_ICTRL), ==, MFT_ICTRL_TAPND);
257
+ cnt = mft_readw(qts, index, MFT_CNT1);
258
+ /*
259
+ * Due to error in clock measurement and rounding, we might have a small
260
+ * error in measuring RPM.
261
+ */
262
+ g_assert_cmphex(cnt + MAX_ERROR, >=, expected_cnt);
263
+ g_assert_cmphex(cnt, <=, expected_cnt + MAX_ERROR);
264
+ cr = mft_readw(qts, index, MFT_CRA);
265
+ g_assert_cmphex(cnt, ==, cr);
60
+ }
266
+ }
61
+
267
+
62
+ if (s->fp_excp_el) {
268
+ /* Verify rpm for fan B */
63
+ gen_exception_insn(s, 4, EXCP_UDEF,
269
+
64
+ syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
270
+ qtest_irq_intercept_out(qts, "/machine/soc/a9mpcore/gic");
65
+ return 0;
271
+}
66
+ }
272
+
67
+ if (!s->vfp_enabled) {
273
/* Check pwm registers can be reset to default value */
68
+ return 1;
274
static void test_init(gconstpointer test_data)
69
+ }
275
{
70
+
276
const TestData *td = test_data;
71
+ opr_sz = (1 + q) * 8;
277
- QTestState *qts = qtest_init("-machine quanta-gsj");
72
+ fpst = get_fpstatus_ptr(1);
278
+ QTestState *qts = qtest_init("-machine npcm750-evb");
73
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
279
int module = pwm_module_index(td->module);
74
+ vfp_reg_offset(1, rn),
280
int pwm = pwm_index(td->pwm);
75
+ vfp_reg_offset(1, rm), fpst,
281
76
+ opr_sz, opr_sz, rot, fn_gvec_ptr);
282
@@ -XXX,XX +XXX,XX @@ static void test_init(gconstpointer test_data)
77
+ tcg_temp_free_ptr(fpst);
283
static void test_oneshot(gconstpointer test_data)
78
+ return 0;
284
{
79
+}
285
const TestData *td = test_data;
80
+
286
- QTestState *qts = qtest_init("-machine quanta-gsj");
81
static int disas_coproc_insn(DisasContext *s, uint32_t insn)
287
+ QTestState *qts = qtest_init("-machine npcm750-evb");
82
{
288
int module = pwm_module_index(td->module);
83
int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
289
int pwm = pwm_index(td->pwm);
84
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
290
uint32_t ppr, csr, pcr;
291
@@ -XXX,XX +XXX,XX @@ static void test_oneshot(gconstpointer test_data)
292
static void test_toggle(gconstpointer test_data)
293
{
294
const TestData *td = test_data;
295
- QTestState *qts = qtest_init("-machine quanta-gsj");
296
+ QTestState *qts = qtest_init("-machine npcm750-evb");
297
int module = pwm_module_index(td->module);
298
int pwm = pwm_index(td->pwm);
299
uint32_t ppr, csr, pcr, cnr, cmr;
300
int i, j, k, l;
301
uint64_t expected_freq, expected_duty;
302
303
+ mft_init(qts, td);
304
+
305
pcr = CH_EN | CH_MOD;
306
for (i = 0; i < ARRAY_SIZE(ppr_list); ++i) {
307
ppr = ppr_list[i];
308
@@ -XXX,XX +XXX,XX @@ static void test_toggle(gconstpointer test_data)
309
==, expected_freq);
85
}
310
}
86
}
311
87
}
312
+ /* Test MFT's RPM is correct. */
88
+ } else if ((insn & 0x0e000a00) == 0x0c000800
313
+ mft_verify_rpm(qts, td, expected_duty);
89
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
314
+
90
+ if (disas_neon_insn_3same_ext(s, insn)) {
315
/* Test inverted mode */
91
+ goto illegal_op;
316
expected_duty = pwm_compute_duty(cnr, cmr, true);
92
+ }
317
pwm_write_pcr(qts, td, pcr | CH_INV);
93
+ return;
94
} else if ((insn & 0x0fe00000) == 0x0c400000) {
95
/* Coprocessor double register transfer. */
96
ARCH(5TE);
97
--
318
--
98
2.16.2
319
2.20.1
99
320
100
321
diff view generated by jsdifflib
1
Instead of loading kernels, device trees, and the like to
1
For a long time now the UI layer has guaranteed that the console
2
the system address space, use the CPU's address space. This
2
surface is always 32 bits per pixel. Remove the legacy dead
3
is important if we're trying to load the file to memory or
3
code from the pl110 display device which was handling the
4
via an alias memory region that is provided by an SoC
4
possibility that the console surface was some other format.
5
object and thus not mapped into the system address space.
6
5
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210211141515.8755-2-peter.maydell@linaro.org
10
Message-id: 20180220180325.29818-3-peter.maydell@linaro.org
11
---
9
---
12
hw/arm/boot.c | 119 +++++++++++++++++++++++++++++++++++++---------------------
10
hw/display/pl110.c | 53 +++++++---------------------------------------
13
1 file changed, 76 insertions(+), 43 deletions(-)
11
1 file changed, 8 insertions(+), 45 deletions(-)
14
12
15
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
13
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/boot.c
15
--- a/hw/display/pl110.c
18
+++ b/hw/arm/boot.c
16
+++ b/hw/display/pl110.c
19
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static const unsigned char *idregs[] = {
20
#define ARM64_TEXT_OFFSET_OFFSET 8
18
pl111_id
21
#define ARM64_MAGIC_OFFSET 56
22
23
+static AddressSpace *arm_boot_address_space(ARMCPU *cpu,
24
+ const struct arm_boot_info *info)
25
+{
26
+ /* Return the address space to use for bootloader reads and writes.
27
+ * We prefer the secure address space if the CPU has it and we're
28
+ * going to boot the guest into it.
29
+ */
30
+ int asidx;
31
+ CPUState *cs = CPU(cpu);
32
+
33
+ if (arm_feature(&cpu->env, ARM_FEATURE_EL3) && info->secure_boot) {
34
+ asidx = ARMASIdx_S;
35
+ } else {
36
+ asidx = ARMASIdx_NS;
37
+ }
38
+
39
+ return cpu_get_address_space(cs, asidx);
40
+}
41
+
42
typedef enum {
43
FIXUP_NONE = 0, /* do nothing */
44
FIXUP_TERMINATOR, /* end of insns */
45
@@ -XXX,XX +XXX,XX @@ static const ARMInsnFixup smpboot[] = {
46
};
19
};
47
20
48
static void write_bootloader(const char *name, hwaddr addr,
21
-#define BITS 8
49
- const ARMInsnFixup *insns, uint32_t *fixupcontext)
22
-#include "pl110_template.h"
50
+ const ARMInsnFixup *insns, uint32_t *fixupcontext,
23
-#define BITS 15
51
+ AddressSpace *as)
24
-#include "pl110_template.h"
52
{
25
-#define BITS 16
53
/* Fix up the specified bootloader fragment and write it into
26
-#include "pl110_template.h"
54
* guest memory using rom_add_blob_fixed(). fixupcontext is
27
-#define BITS 24
55
@@ -XXX,XX +XXX,XX @@ static void write_bootloader(const char *name, hwaddr addr,
28
-#include "pl110_template.h"
56
code[i] = tswap32(insn);
29
#define BITS 32
57
}
30
#include "pl110_template.h"
58
31
59
- rom_add_blob_fixed(name, code, len * sizeof(uint32_t), addr);
32
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
60
+ rom_add_blob_fixed_as(name, code, len * sizeof(uint32_t), addr, as);
33
PL110State *s = (PL110State *)opaque;
61
34
SysBusDevice *sbd;
62
g_free(code);
35
DisplaySurface *surface = qemu_console_surface(s->con);
63
}
36
- drawfn* fntable;
64
@@ -XXX,XX +XXX,XX @@ static void default_write_secondary(ARMCPU *cpu,
37
drawfn fn;
65
const struct arm_boot_info *info)
38
- int dest_width;
66
{
39
int src_width;
67
uint32_t fixupcontext[FIXUP_MAX];
40
int bpp_offset;
68
+ AddressSpace *as = arm_boot_address_space(cpu, info);
41
int first;
69
42
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
70
fixupcontext[FIXUP_GIC_CPU_IF] = info->gic_cpu_if_addr;
43
71
fixupcontext[FIXUP_BOOTREG] = info->smp_bootreg_addr;
44
sbd = SYS_BUS_DEVICE(s);
72
@@ -XXX,XX +XXX,XX @@ static void default_write_secondary(ARMCPU *cpu,
45
73
}
46
- switch (surface_bits_per_pixel(surface)) {
74
47
- case 0:
75
write_bootloader("smpboot", info->smp_loader_start,
48
- return;
76
- smpboot, fixupcontext);
49
- case 8:
77
+ smpboot, fixupcontext, as);
50
- fntable = pl110_draw_fn_8;
78
}
51
- dest_width = 1;
79
52
- break;
80
void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
53
- case 15:
81
const struct arm_boot_info *info,
54
- fntable = pl110_draw_fn_15;
82
hwaddr mvbar_addr)
55
- dest_width = 2;
83
{
56
- break;
84
+ AddressSpace *as = arm_boot_address_space(cpu, info);
57
- case 16:
85
int n;
58
- fntable = pl110_draw_fn_16;
86
uint32_t mvbar_blob[] = {
59
- dest_width = 2;
87
/* mvbar_addr: secure monitor vectors
60
- break;
88
@@ -XXX,XX +XXX,XX @@ void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
61
- case 24:
89
for (n = 0; n < ARRAY_SIZE(mvbar_blob); n++) {
62
- fntable = pl110_draw_fn_24;
90
mvbar_blob[n] = tswap32(mvbar_blob[n]);
63
- dest_width = 3;
91
}
64
- break;
92
- rom_add_blob_fixed("board-setup-mvbar", mvbar_blob, sizeof(mvbar_blob),
65
- case 32:
93
- mvbar_addr);
66
- fntable = pl110_draw_fn_32;
94
+ rom_add_blob_fixed_as("board-setup-mvbar", mvbar_blob, sizeof(mvbar_blob),
67
- dest_width = 4;
95
+ mvbar_addr, as);
68
- break;
96
69
- default:
97
for (n = 0; n < ARRAY_SIZE(board_setup_blob); n++) {
70
- fprintf(stderr, "pl110: Bad color depth\n");
98
board_setup_blob[n] = tswap32(board_setup_blob[n]);
71
- exit(1);
99
}
72
- }
100
- rom_add_blob_fixed("board-setup", board_setup_blob,
73
if (s->cr & PL110_CR_BGR)
101
- sizeof(board_setup_blob), info->board_setup_addr);
74
bpp_offset = 0;
102
+ rom_add_blob_fixed_as("board-setup", board_setup_blob,
75
else
103
+ sizeof(board_setup_blob), info->board_setup_addr, as);
76
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
104
}
105
106
static void default_reset_secondary(ARMCPU *cpu,
107
const struct arm_boot_info *info)
108
{
109
+ AddressSpace *as = arm_boot_address_space(cpu, info);
110
CPUState *cs = CPU(cpu);
111
112
- address_space_stl_notdirty(&address_space_memory, info->smp_bootreg_addr,
113
+ address_space_stl_notdirty(as, info->smp_bootreg_addr,
114
0, MEMTXATTRS_UNSPECIFIED, NULL);
115
cpu_set_pc(cs, info->smp_loader_start);
116
}
117
@@ -XXX,XX +XXX,XX @@ static inline bool have_dtb(const struct arm_boot_info *info)
118
}
119
120
#define WRITE_WORD(p, value) do { \
121
- address_space_stl_notdirty(&address_space_memory, p, value, \
122
+ address_space_stl_notdirty(as, p, value, \
123
MEMTXATTRS_UNSPECIFIED, NULL); \
124
p += 4; \
125
} while (0)
126
127
-static void set_kernel_args(const struct arm_boot_info *info)
128
+static void set_kernel_args(const struct arm_boot_info *info, AddressSpace *as)
129
{
130
int initrd_size = info->initrd_size;
131
hwaddr base = info->loader_start;
132
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
133
int cmdline_size;
134
135
cmdline_size = strlen(info->kernel_cmdline);
136
- cpu_physical_memory_write(p + 8, info->kernel_cmdline,
137
- cmdline_size + 1);
138
+ address_space_write(as, p + 8, MEMTXATTRS_UNSPECIFIED,
139
+ (const uint8_t *)info->kernel_cmdline,
140
+ cmdline_size + 1);
141
cmdline_size = (cmdline_size >> 2) + 1;
142
WRITE_WORD(p, cmdline_size + 2);
143
WRITE_WORD(p, 0x54410009);
144
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
145
atag_board_len = (info->atag_board(info, atag_board_buf) + 3) & ~3;
146
WRITE_WORD(p, (atag_board_len + 8) >> 2);
147
WRITE_WORD(p, 0x414f4d50);
148
- cpu_physical_memory_write(p, atag_board_buf, atag_board_len);
149
+ address_space_write(as, p, MEMTXATTRS_UNSPECIFIED,
150
+ atag_board_buf, atag_board_len);
151
p += atag_board_len;
152
}
153
/* ATAG_END */
154
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
155
WRITE_WORD(p, 0);
156
}
157
158
-static void set_kernel_args_old(const struct arm_boot_info *info)
159
+static void set_kernel_args_old(const struct arm_boot_info *info,
160
+ AddressSpace *as)
161
{
162
hwaddr p;
163
const char *s;
164
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args_old(const struct arm_boot_info *info)
165
}
166
s = info->kernel_cmdline;
167
if (s) {
168
- cpu_physical_memory_write(p, s, strlen(s) + 1);
169
+ address_space_write(as, p, MEMTXATTRS_UNSPECIFIED,
170
+ (const uint8_t *)s, strlen(s) + 1);
171
} else {
172
WRITE_WORD(p, 0);
173
}
174
@@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt)
175
* @addr: the address to load the image at
176
* @binfo: struct describing the boot environment
177
* @addr_limit: upper limit of the available memory area at @addr
178
+ * @as: address space to load image to
179
*
180
* Load a device tree supplied by the machine or by the user with the
181
* '-dtb' command line option, and put it at offset @addr in target
182
@@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt)
183
* Note: Must not be called unless have_dtb(binfo) is true.
184
*/
185
static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
186
- hwaddr addr_limit)
187
+ hwaddr addr_limit, AddressSpace *as)
188
{
189
void *fdt = NULL;
190
int size, rc;
191
@@ -XXX,XX +XXX,XX @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
192
/* Put the DTB into the memory map as a ROM image: this will ensure
193
* the DTB is copied again upon reset, even if addr points into RAM.
194
*/
195
- rom_add_blob_fixed("dtb", fdt, size, addr);
196
+ rom_add_blob_fixed_as("dtb", fdt, size, addr, as);
197
198
g_free(fdt);
199
200
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
201
}
202
203
if (cs == first_cpu) {
204
+ AddressSpace *as = arm_boot_address_space(cpu, info);
205
+
206
cpu_set_pc(cs, info->loader_start);
207
208
if (!have_dtb(info)) {
209
if (old_param) {
210
- set_kernel_args_old(info);
211
+ set_kernel_args_old(info, as);
212
} else {
213
- set_kernel_args(info);
214
+ set_kernel_args(info, as);
215
}
216
}
217
} else {
218
@@ -XXX,XX +XXX,XX @@ static int do_arm_linux_init(Object *obj, void *opaque)
219
220
static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
221
uint64_t *lowaddr, uint64_t *highaddr,
222
- int elf_machine)
223
+ int elf_machine, AddressSpace *as)
224
{
225
bool elf_is64;
226
union {
227
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
228
}
77
}
229
}
78
}
230
79
231
- ret = load_elf(info->kernel_filename, NULL, NULL,
80
- if (s->cr & PL110_CR_BEBO)
232
- pentry, lowaddr, highaddr, big_endian, elf_machine,
81
- fn = fntable[s->bpp + 8 + bpp_offset];
233
- 1, data_swab);
82
- else if (s->cr & PL110_CR_BEPO)
234
+ ret = load_elf_as(info->kernel_filename, NULL, NULL,
83
- fn = fntable[s->bpp + 16 + bpp_offset];
235
+ pentry, lowaddr, highaddr, big_endian, elf_machine,
84
- else
236
+ 1, data_swab, as);
85
- fn = fntable[s->bpp + bpp_offset];
237
if (ret <= 0) {
86
+ if (s->cr & PL110_CR_BEBO) {
238
/* The header loaded but the image didn't */
87
+ fn = pl110_draw_fn_32[s->bpp + 8 + bpp_offset];
239
exit(1);
88
+ } else if (s->cr & PL110_CR_BEPO) {
240
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
89
+ fn = pl110_draw_fn_32[s->bpp + 16 + bpp_offset];
241
}
90
+ } else {
242
91
+ fn = pl110_draw_fn_32[s->bpp + bpp_offset];
243
static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
92
+ }
244
- hwaddr *entry)
93
245
+ hwaddr *entry, AddressSpace *as)
94
src_width = s->cols;
246
{
95
switch (s->bpp) {
247
hwaddr kernel_load_offset = KERNEL64_LOAD_ADDR;
96
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
248
uint8_t *buffer;
97
src_width <<= 2;
249
@@ -XXX,XX +XXX,XX @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
98
break;
250
}
99
}
251
100
- dest_width *= s->cols;
252
*entry = mem_base + kernel_load_offset;
101
first = 0;
253
- rom_add_blob_fixed(filename, buffer, size, *entry);
102
if (s->invalidate) {
254
+ rom_add_blob_fixed_as(filename, buffer, size, *entry, as);
103
framebuffer_update_memory_section(&s->fbsection,
255
104
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
256
g_free(buffer);
105
257
106
framebuffer_update_display(surface, &s->fbsection,
258
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
107
s->cols, s->rows,
259
ARMCPU *cpu = n->cpu;
108
- src_width, dest_width, 0,
260
struct arm_boot_info *info =
109
+ src_width, s->cols * 4, 0,
261
container_of(n, struct arm_boot_info, load_kernel_notifier);
110
s->invalidate,
262
+ AddressSpace *as = arm_boot_address_space(cpu, info);
111
fn, s->palette,
263
112
&first, &last);
264
/* The board code is not supposed to set secure_board_setup unless
265
* running its code in secure mode is actually possible, and KVM
266
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
267
* the kernel is supposed to be loaded by the bootloader), copy the
268
* DTB to the base of RAM for the bootloader to pick up.
269
*/
270
- if (load_dtb(info->loader_start, info, 0) < 0) {
271
+ if (load_dtb(info->loader_start, info, 0, as) < 0) {
272
exit(1);
273
}
274
}
275
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
276
277
/* Assume that raw images are linux kernels, and ELF images are not. */
278
kernel_size = arm_load_elf(info, &elf_entry, &elf_low_addr,
279
- &elf_high_addr, elf_machine);
280
+ &elf_high_addr, elf_machine, as);
281
if (kernel_size > 0 && have_dtb(info)) {
282
/* If there is still some room left at the base of RAM, try and put
283
* the DTB there like we do for images loaded with -bios or -pflash.
284
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
285
if (elf_low_addr < info->loader_start) {
286
elf_low_addr = 0;
287
}
288
- if (load_dtb(info->loader_start, info, elf_low_addr) < 0) {
289
+ if (load_dtb(info->loader_start, info, elf_low_addr, as) < 0) {
290
exit(1);
291
}
292
}
293
}
294
entry = elf_entry;
295
if (kernel_size < 0) {
296
- kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
297
- &is_linux, NULL, NULL);
298
+ kernel_size = load_uimage_as(info->kernel_filename, &entry, NULL,
299
+ &is_linux, NULL, NULL, as);
300
}
301
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && kernel_size < 0) {
302
kernel_size = load_aarch64_image(info->kernel_filename,
303
- info->loader_start, &entry);
304
+ info->loader_start, &entry, as);
305
is_linux = 1;
306
} else if (kernel_size < 0) {
307
/* 32-bit ARM */
308
entry = info->loader_start + KERNEL_LOAD_ADDR;
309
- kernel_size = load_image_targphys(info->kernel_filename, entry,
310
- info->ram_size - KERNEL_LOAD_ADDR);
311
+ kernel_size = load_image_targphys_as(info->kernel_filename, entry,
312
+ info->ram_size - KERNEL_LOAD_ADDR,
313
+ as);
314
is_linux = 1;
315
}
316
if (kernel_size < 0) {
317
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
318
uint32_t fixupcontext[FIXUP_MAX];
319
320
if (info->initrd_filename) {
321
- initrd_size = load_ramdisk(info->initrd_filename,
322
- info->initrd_start,
323
- info->ram_size -
324
- info->initrd_start);
325
+ initrd_size = load_ramdisk_as(info->initrd_filename,
326
+ info->initrd_start,
327
+ info->ram_size - info->initrd_start,
328
+ as);
329
if (initrd_size < 0) {
330
- initrd_size = load_image_targphys(info->initrd_filename,
331
- info->initrd_start,
332
- info->ram_size -
333
- info->initrd_start);
334
+ initrd_size = load_image_targphys_as(info->initrd_filename,
335
+ info->initrd_start,
336
+ info->ram_size -
337
+ info->initrd_start,
338
+ as);
339
}
340
if (initrd_size < 0) {
341
error_report("could not load initrd '%s'",
342
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
343
344
/* Place the DTB after the initrd in memory with alignment. */
345
dtb_start = QEMU_ALIGN_UP(info->initrd_start + initrd_size, align);
346
- if (load_dtb(dtb_start, info, 0) < 0) {
347
+ if (load_dtb(dtb_start, info, 0, as) < 0) {
348
exit(1);
349
}
350
fixupcontext[FIXUP_ARGPTR] = dtb_start;
351
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
352
fixupcontext[FIXUP_ENTRYPOINT] = entry;
353
354
write_bootloader("bootloader", info->loader_start,
355
- primary_loader, fixupcontext);
356
+ primary_loader, fixupcontext, as);
357
358
if (info->nb_cpus > 1) {
359
info->write_secondary_boot(cpu, info);
360
--
113
--
361
2.16.2
114
2.20.1
362
115
363
116
diff view generated by jsdifflib
1
In v8M, the Implementation Defined Attribution Unit (IDAU) is
1
The pl110_template.h header has a doubly-nested multiple-include pattern:
2
a small piece of hardware typically implemented in the SoC
2
* pl110.c includes it once for each host bit depth (now always 32)
3
which provides board or SoC specific security attribution
3
* every time it is included, it includes itself 6 times, to account
4
information for each address that the CPU performs MPU/SAU
4
for multiple guest device pixel and byte orders
5
checks on. For QEMU, we model this with a QOM interface which
5
6
is implemented by the board or SoC object and connected to
6
Now we only have to deal with 32-bit host bit depths, we can move the
7
the CPU using a link property.
7
code corresponding to the outer layer of this double-nesting to be
8
8
directly in pl110.c and reduce the template header to a single layer
9
This commit defines the new interface class, adds the link
9
of nesting.
10
property to the CPU object, and makes the SAU checking
11
code call the IDAU interface if one is present.
12
10
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
15
Message-id: 20180220180325.29818-5-peter.maydell@linaro.org
13
Message-id: 20210211141515.8755-3-peter.maydell@linaro.org
16
---
14
---
17
target/arm/cpu.h | 3 +++
15
hw/display/pl110_template.h | 100 +-----------------------------------
18
target/arm/idau.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++
16
hw/display/pl110.c | 79 ++++++++++++++++++++++++++++
19
target/arm/cpu.c | 15 +++++++++++++
17
2 files changed, 80 insertions(+), 99 deletions(-)
20
target/arm/helper.c | 28 +++++++++++++++++++++---
18
21
4 files changed, 104 insertions(+), 3 deletions(-)
19
diff --git a/hw/display/pl110_template.h b/hw/display/pl110_template.h
22
create mode 100644 target/arm/idau.h
23
24
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
25
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/cpu.h
21
--- a/hw/display/pl110_template.h
27
+++ b/target/arm/cpu.h
22
+++ b/hw/display/pl110_template.h
28
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
29
/* MemoryRegion to use for secure physical accesses */
30
MemoryRegion *secure_memory;
31
32
+ /* For v8M, pointer to the IDAU interface provided by board/SoC */
33
+ Object *idau;
34
+
35
/* 'compatible' string for this CPU for Linux device trees */
36
const char *dtb_compatible;
37
38
diff --git a/target/arm/idau.h b/target/arm/idau.h
39
new file mode 100644
40
index XXXXXXX..XXXXXXX
41
--- /dev/null
42
+++ b/target/arm/idau.h
43
@@ -XXX,XX +XXX,XX @@
44
+/*
45
+ * QEMU ARM CPU -- interface for the Arm v8M IDAU
46
+ *
47
+ * Copyright (c) 2018 Linaro Ltd
48
+ *
49
+ * This program is free software; you can redistribute it and/or
50
+ * modify it under the terms of the GNU General Public License
51
+ * as published by the Free Software Foundation; either version 2
52
+ * of the License, or (at your option) any later version.
53
+ *
54
+ * This program is distributed in the hope that it will be useful,
55
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
56
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57
+ * GNU General Public License for more details.
58
+ *
59
+ * You should have received a copy of the GNU General Public License
60
+ * along with this program; if not, see
61
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
62
+ *
63
+ * In the v8M architecture, the IDAU is a small piece of hardware
64
+ * typically implemented in the SoC which provides board or SoC
65
+ * specific security attribution information for each address that
66
+ * the CPU performs MPU/SAU checks on. For QEMU, we model this with a
67
+ * QOM interface which is implemented by the board or SoC object and
68
+ * connected to the CPU using a link property.
69
+ */
70
+
71
+#ifndef TARGET_ARM_IDAU_H
72
+#define TARGET_ARM_IDAU_H
73
+
74
+#include "qom/object.h"
75
+
76
+#define TYPE_IDAU_INTERFACE "idau-interface"
77
+#define IDAU_INTERFACE(obj) \
78
+ INTERFACE_CHECK(IDAUInterface, (obj), TYPE_IDAU_INTERFACE)
79
+#define IDAU_INTERFACE_CLASS(class) \
80
+ OBJECT_CLASS_CHECK(IDAUInterfaceClass, (class), TYPE_IDAU_INTERFACE)
81
+#define IDAU_INTERFACE_GET_CLASS(obj) \
82
+ OBJECT_GET_CLASS(IDAUInterfaceClass, (obj), TYPE_IDAU_INTERFACE)
83
+
84
+typedef struct IDAUInterface {
85
+ Object parent;
86
+} IDAUInterface;
87
+
88
+#define IREGION_NOTVALID -1
89
+
90
+typedef struct IDAUInterfaceClass {
91
+ InterfaceClass parent;
92
+
93
+ /* Check the specified address and return the IDAU security information
94
+ * for it by filling in iregion, exempt, ns and nsc:
95
+ * iregion: IDAU region number, or IREGION_NOTVALID if not valid
96
+ * exempt: true if address is exempt from security attribution
97
+ * ns: true if the address is NonSecure
98
+ * nsc: true if the address is NonSecure-callable
99
+ */
100
+ void (*check)(IDAUInterface *ii, uint32_t address, int *iregion,
101
+ bool *exempt, bool *ns, bool *nsc);
102
+} IDAUInterfaceClass;
103
+
104
+#endif
105
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/cpu.c
108
+++ b/target/arm/cpu.c
109
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
110
*/
24
*/
111
25
112
#include "qemu/osdep.h"
26
#ifndef ORDER
113
+#include "target/arm/idau.h"
27
-
114
#include "qemu/error-report.h"
28
-#if BITS == 8
115
#include "qapi/error.h"
29
-#define COPY_PIXEL(to, from) *(to++) = from
116
#include "cpu.h"
30
-#elif BITS == 15 || BITS == 16
117
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_post_init(Object *obj)
31
-#define COPY_PIXEL(to, from) do { *(uint16_t *)to = from; to += 2; } while (0)
118
}
32
-#elif BITS == 24
119
}
33
-#define COPY_PIXEL(to, from) \
120
34
- do { \
121
+ if (arm_feature(&cpu->env, ARM_FEATURE_M_SECURITY)) {
35
- *(to++) = from; \
122
+ object_property_add_link(obj, "idau", TYPE_IDAU_INTERFACE, &cpu->idau,
36
- *(to++) = (from) >> 8; \
123
+ qdev_prop_allow_set_link_before_realize,
37
- *(to++) = (from) >> 16; \
124
+ OBJ_PROP_LINK_UNREF_ON_RELEASE,
38
- } while (0)
125
+ &error_abort);
39
-#elif BITS == 32
126
+ }
40
-#define COPY_PIXEL(to, from) do { *(uint32_t *)to = from; to += 4; } while (0)
127
+
41
-#else
128
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
42
-#error unknown bit depth
129
&error_abort);
43
+#error "pl110_template.h is only for inclusion by pl110.c"
130
}
44
#endif
131
@@ -XXX,XX +XXX,XX @@ static const TypeInfo arm_cpu_type_info = {
45
132
.class_init = arm_cpu_class_init,
46
-#undef RGB
47
-#define BORDER bgr
48
-#define ORDER 0
49
-#include "pl110_template.h"
50
-#define ORDER 1
51
-#include "pl110_template.h"
52
-#define ORDER 2
53
-#include "pl110_template.h"
54
-#undef BORDER
55
-#define RGB
56
-#define BORDER rgb
57
-#define ORDER 0
58
-#include "pl110_template.h"
59
-#define ORDER 1
60
-#include "pl110_template.h"
61
-#define ORDER 2
62
-#include "pl110_template.h"
63
-#undef BORDER
64
-
65
-static drawfn glue(pl110_draw_fn_,BITS)[48] =
66
-{
67
- glue(pl110_draw_line1_lblp_bgr,BITS),
68
- glue(pl110_draw_line2_lblp_bgr,BITS),
69
- glue(pl110_draw_line4_lblp_bgr,BITS),
70
- glue(pl110_draw_line8_lblp_bgr,BITS),
71
- glue(pl110_draw_line16_555_lblp_bgr,BITS),
72
- glue(pl110_draw_line32_lblp_bgr,BITS),
73
- glue(pl110_draw_line16_lblp_bgr,BITS),
74
- glue(pl110_draw_line12_lblp_bgr,BITS),
75
-
76
- glue(pl110_draw_line1_bbbp_bgr,BITS),
77
- glue(pl110_draw_line2_bbbp_bgr,BITS),
78
- glue(pl110_draw_line4_bbbp_bgr,BITS),
79
- glue(pl110_draw_line8_bbbp_bgr,BITS),
80
- glue(pl110_draw_line16_555_bbbp_bgr,BITS),
81
- glue(pl110_draw_line32_bbbp_bgr,BITS),
82
- glue(pl110_draw_line16_bbbp_bgr,BITS),
83
- glue(pl110_draw_line12_bbbp_bgr,BITS),
84
-
85
- glue(pl110_draw_line1_lbbp_bgr,BITS),
86
- glue(pl110_draw_line2_lbbp_bgr,BITS),
87
- glue(pl110_draw_line4_lbbp_bgr,BITS),
88
- glue(pl110_draw_line8_lbbp_bgr,BITS),
89
- glue(pl110_draw_line16_555_lbbp_bgr,BITS),
90
- glue(pl110_draw_line32_lbbp_bgr,BITS),
91
- glue(pl110_draw_line16_lbbp_bgr,BITS),
92
- glue(pl110_draw_line12_lbbp_bgr,BITS),
93
-
94
- glue(pl110_draw_line1_lblp_rgb,BITS),
95
- glue(pl110_draw_line2_lblp_rgb,BITS),
96
- glue(pl110_draw_line4_lblp_rgb,BITS),
97
- glue(pl110_draw_line8_lblp_rgb,BITS),
98
- glue(pl110_draw_line16_555_lblp_rgb,BITS),
99
- glue(pl110_draw_line32_lblp_rgb,BITS),
100
- glue(pl110_draw_line16_lblp_rgb,BITS),
101
- glue(pl110_draw_line12_lblp_rgb,BITS),
102
-
103
- glue(pl110_draw_line1_bbbp_rgb,BITS),
104
- glue(pl110_draw_line2_bbbp_rgb,BITS),
105
- glue(pl110_draw_line4_bbbp_rgb,BITS),
106
- glue(pl110_draw_line8_bbbp_rgb,BITS),
107
- glue(pl110_draw_line16_555_bbbp_rgb,BITS),
108
- glue(pl110_draw_line32_bbbp_rgb,BITS),
109
- glue(pl110_draw_line16_bbbp_rgb,BITS),
110
- glue(pl110_draw_line12_bbbp_rgb,BITS),
111
-
112
- glue(pl110_draw_line1_lbbp_rgb,BITS),
113
- glue(pl110_draw_line2_lbbp_rgb,BITS),
114
- glue(pl110_draw_line4_lbbp_rgb,BITS),
115
- glue(pl110_draw_line8_lbbp_rgb,BITS),
116
- glue(pl110_draw_line16_555_lbbp_rgb,BITS),
117
- glue(pl110_draw_line32_lbbp_rgb,BITS),
118
- glue(pl110_draw_line16_lbbp_rgb,BITS),
119
- glue(pl110_draw_line12_lbbp_rgb,BITS),
120
-};
121
-
122
-#undef BITS
123
-#undef COPY_PIXEL
124
-
125
-#else
126
-
127
#if ORDER == 0
128
#define NAME glue(glue(lblp_, BORDER), BITS)
129
#ifdef HOST_WORDS_BIGENDIAN
130
@@ -XXX,XX +XXX,XX @@ static void glue(pl110_draw_line12_,NAME)(void *opaque, uint8_t *d, const uint8_
131
#undef NAME
132
#undef SWAP_WORDS
133
#undef ORDER
134
-
135
-#endif
136
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
137
index XXXXXXX..XXXXXXX 100644
138
--- a/hw/display/pl110.c
139
+++ b/hw/display/pl110.c
140
@@ -XXX,XX +XXX,XX @@ static const unsigned char *idregs[] = {
133
};
141
};
134
142
135
+static const TypeInfo idau_interface_type_info = {
143
#define BITS 32
136
+ .name = TYPE_IDAU_INTERFACE,
144
+#define COPY_PIXEL(to, from) do { *(uint32_t *)to = from; to += 4; } while (0)
137
+ .parent = TYPE_INTERFACE,
145
+
138
+ .class_size = sizeof(IDAUInterfaceClass),
146
+#undef RGB
147
+#define BORDER bgr
148
+#define ORDER 0
149
#include "pl110_template.h"
150
+#define ORDER 1
151
+#include "pl110_template.h"
152
+#define ORDER 2
153
+#include "pl110_template.h"
154
+#undef BORDER
155
+#define RGB
156
+#define BORDER rgb
157
+#define ORDER 0
158
+#include "pl110_template.h"
159
+#define ORDER 1
160
+#include "pl110_template.h"
161
+#define ORDER 2
162
+#include "pl110_template.h"
163
+#undef BORDER
164
+
165
+static drawfn pl110_draw_fn_32[48] = {
166
+ pl110_draw_line1_lblp_bgr32,
167
+ pl110_draw_line2_lblp_bgr32,
168
+ pl110_draw_line4_lblp_bgr32,
169
+ pl110_draw_line8_lblp_bgr32,
170
+ pl110_draw_line16_555_lblp_bgr32,
171
+ pl110_draw_line32_lblp_bgr32,
172
+ pl110_draw_line16_lblp_bgr32,
173
+ pl110_draw_line12_lblp_bgr32,
174
+
175
+ pl110_draw_line1_bbbp_bgr32,
176
+ pl110_draw_line2_bbbp_bgr32,
177
+ pl110_draw_line4_bbbp_bgr32,
178
+ pl110_draw_line8_bbbp_bgr32,
179
+ pl110_draw_line16_555_bbbp_bgr32,
180
+ pl110_draw_line32_bbbp_bgr32,
181
+ pl110_draw_line16_bbbp_bgr32,
182
+ pl110_draw_line12_bbbp_bgr32,
183
+
184
+ pl110_draw_line1_lbbp_bgr32,
185
+ pl110_draw_line2_lbbp_bgr32,
186
+ pl110_draw_line4_lbbp_bgr32,
187
+ pl110_draw_line8_lbbp_bgr32,
188
+ pl110_draw_line16_555_lbbp_bgr32,
189
+ pl110_draw_line32_lbbp_bgr32,
190
+ pl110_draw_line16_lbbp_bgr32,
191
+ pl110_draw_line12_lbbp_bgr32,
192
+
193
+ pl110_draw_line1_lblp_rgb32,
194
+ pl110_draw_line2_lblp_rgb32,
195
+ pl110_draw_line4_lblp_rgb32,
196
+ pl110_draw_line8_lblp_rgb32,
197
+ pl110_draw_line16_555_lblp_rgb32,
198
+ pl110_draw_line32_lblp_rgb32,
199
+ pl110_draw_line16_lblp_rgb32,
200
+ pl110_draw_line12_lblp_rgb32,
201
+
202
+ pl110_draw_line1_bbbp_rgb32,
203
+ pl110_draw_line2_bbbp_rgb32,
204
+ pl110_draw_line4_bbbp_rgb32,
205
+ pl110_draw_line8_bbbp_rgb32,
206
+ pl110_draw_line16_555_bbbp_rgb32,
207
+ pl110_draw_line32_bbbp_rgb32,
208
+ pl110_draw_line16_bbbp_rgb32,
209
+ pl110_draw_line12_bbbp_rgb32,
210
+
211
+ pl110_draw_line1_lbbp_rgb32,
212
+ pl110_draw_line2_lbbp_rgb32,
213
+ pl110_draw_line4_lbbp_rgb32,
214
+ pl110_draw_line8_lbbp_rgb32,
215
+ pl110_draw_line16_555_lbbp_rgb32,
216
+ pl110_draw_line32_lbbp_rgb32,
217
+ pl110_draw_line16_lbbp_rgb32,
218
+ pl110_draw_line12_lbbp_rgb32,
139
+};
219
+};
140
+
220
+
141
static void arm_cpu_register_types(void)
221
+#undef BITS
222
+#undef COPY_PIXEL
223
+
224
225
static int pl110_enabled(PL110State *s)
142
{
226
{
143
const ARMCPUInfo *info = arm_cpus;
144
145
type_register_static(&arm_cpu_type_info);
146
+ type_register_static(&idau_interface_type_info);
147
148
while (info->name) {
149
cpu_register(info);
150
diff --git a/target/arm/helper.c b/target/arm/helper.c
151
index XXXXXXX..XXXXXXX 100644
152
--- a/target/arm/helper.c
153
+++ b/target/arm/helper.c
154
@@ -XXX,XX +XXX,XX @@
155
#include "qemu/osdep.h"
156
+#include "target/arm/idau.h"
157
#include "trace.h"
158
#include "cpu.h"
159
#include "internals.h"
160
@@ -XXX,XX +XXX,XX @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address,
161
*/
162
ARMCPU *cpu = arm_env_get_cpu(env);
163
int r;
164
+ bool idau_exempt = false, idau_ns = true, idau_nsc = true;
165
+ int idau_region = IREGION_NOTVALID;
166
167
- /* TODO: implement IDAU */
168
+ if (cpu->idau) {
169
+ IDAUInterfaceClass *iic = IDAU_INTERFACE_GET_CLASS(cpu->idau);
170
+ IDAUInterface *ii = IDAU_INTERFACE(cpu->idau);
171
+
172
+ iic->check(ii, address, &idau_region, &idau_exempt, &idau_ns,
173
+ &idau_nsc);
174
+ }
175
176
if (access_type == MMU_INST_FETCH && extract32(address, 28, 4) == 0xf) {
177
/* 0xf0000000..0xffffffff is always S for insn fetches */
178
return;
179
}
180
181
- if (v8m_is_sau_exempt(env, address, access_type)) {
182
+ if (idau_exempt || v8m_is_sau_exempt(env, address, access_type)) {
183
sattrs->ns = !regime_is_secure(env, mmu_idx);
184
return;
185
}
186
187
+ if (idau_region != IREGION_NOTVALID) {
188
+ sattrs->irvalid = true;
189
+ sattrs->iregion = idau_region;
190
+ }
191
+
192
switch (env->sau.ctrl & 3) {
193
case 0: /* SAU.ENABLE == 0, SAU.ALLNS == 0 */
194
break;
195
@@ -XXX,XX +XXX,XX @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address,
196
}
197
}
198
199
- /* TODO when we support the IDAU then it may override the result here */
200
+ /* The IDAU will override the SAU lookup results if it specifies
201
+ * higher security than the SAU does.
202
+ */
203
+ if (!idau_ns) {
204
+ if (sattrs->ns || (!idau_nsc && sattrs->nsc)) {
205
+ sattrs->ns = false;
206
+ sattrs->nsc = idau_nsc;
207
+ }
208
+ }
209
break;
210
}
211
}
212
--
227
--
213
2.16.2
228
2.20.1
214
229
215
230
diff view generated by jsdifflib
1
Move the definition of the struct for the unimplemented-device
1
BITS is always 32, so remove all uses of it from the template header,
2
from unimp.c to unimp.h, so that users can embed the struct
2
by dropping the trailing '32' from the draw function names and
3
in their own device structs if they prefer.
3
not constructing the name of rgb_to_pixel32() via the glue() macro.
4
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210211141515.8755-4-peter.maydell@linaro.org
8
Message-id: 20180220180325.29818-10-peter.maydell@linaro.org
9
---
8
---
10
include/hw/misc/unimp.h | 10 ++++++++++
9
hw/display/pl110_template.h | 20 +++----
11
hw/misc/unimp.c | 10 ----------
10
hw/display/pl110.c | 113 ++++++++++++++++++------------------
12
2 files changed, 10 insertions(+), 10 deletions(-)
11
2 files changed, 65 insertions(+), 68 deletions(-)
13
12
14
diff --git a/include/hw/misc/unimp.h b/include/hw/misc/unimp.h
13
diff --git a/hw/display/pl110_template.h b/hw/display/pl110_template.h
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/misc/unimp.h
15
--- a/hw/display/pl110_template.h
17
+++ b/include/hw/misc/unimp.h
16
+++ b/hw/display/pl110_template.h
18
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@
19
18
#endif
20
#define TYPE_UNIMPLEMENTED_DEVICE "unimplemented-device"
19
21
20
#if ORDER == 0
22
+#define UNIMPLEMENTED_DEVICE(obj) \
21
-#define NAME glue(glue(lblp_, BORDER), BITS)
23
+ OBJECT_CHECK(UnimplementedDeviceState, (obj), TYPE_UNIMPLEMENTED_DEVICE)
22
+#define NAME glue(lblp_, BORDER)
24
+
23
#ifdef HOST_WORDS_BIGENDIAN
25
+typedef struct {
24
#define SWAP_WORDS 1
26
+ SysBusDevice parent_obj;
25
#endif
27
+ MemoryRegion iomem;
26
#elif ORDER == 1
28
+ char *name;
27
-#define NAME glue(glue(bbbp_, BORDER), BITS)
29
+ uint64_t size;
28
+#define NAME glue(bbbp_, BORDER)
30
+} UnimplementedDeviceState;
29
#ifndef HOST_WORDS_BIGENDIAN
31
+
30
#define SWAP_WORDS 1
32
/**
31
#endif
33
* create_unimplemented_device: create and map a dummy device
32
#else
34
* @name: name of the device for debug logging
33
#define SWAP_PIXELS 1
35
diff --git a/hw/misc/unimp.c b/hw/misc/unimp.c
34
-#define NAME glue(glue(lbbp_, BORDER), BITS)
35
+#define NAME glue(lbbp_, BORDER)
36
#ifdef HOST_WORDS_BIGENDIAN
37
#define SWAP_WORDS 1
38
#endif
39
@@ -XXX,XX +XXX,XX @@ static void glue(pl110_draw_line16_,NAME)(void *opaque, uint8_t *d, const uint8_
40
MSB = (data & 0x1f) << 3;
41
data >>= 5;
42
#endif
43
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
44
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
45
LSB = (data & 0x1f) << 3;
46
data >>= 5;
47
g = (data & 0x3f) << 2;
48
data >>= 6;
49
MSB = (data & 0x1f) << 3;
50
data >>= 5;
51
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
52
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
53
#undef MSB
54
#undef LSB
55
width -= 2;
56
@@ -XXX,XX +XXX,XX @@ static void glue(pl110_draw_line32_,NAME)(void *opaque, uint8_t *d, const uint8_
57
g = (data >> 16) & 0xff;
58
MSB = (data >> 8) & 0xff;
59
#endif
60
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
61
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
62
#undef MSB
63
#undef LSB
64
width--;
65
@@ -XXX,XX +XXX,XX @@ static void glue(pl110_draw_line16_555_,NAME)(void *opaque, uint8_t *d, const ui
66
data >>= 5;
67
MSB = (data & 0x1f) << 3;
68
data >>= 5;
69
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
70
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
71
LSB = (data & 0x1f) << 3;
72
data >>= 5;
73
g = (data & 0x1f) << 3;
74
data >>= 5;
75
MSB = (data & 0x1f) << 3;
76
data >>= 6;
77
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
78
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
79
#undef MSB
80
#undef LSB
81
width -= 2;
82
@@ -XXX,XX +XXX,XX @@ static void glue(pl110_draw_line12_,NAME)(void *opaque, uint8_t *d, const uint8_
83
data >>= 4;
84
MSB = (data & 0xf) << 4;
85
data >>= 8;
86
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
87
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
88
LSB = (data & 0xf) << 4;
89
data >>= 4;
90
g = (data & 0xf) << 4;
91
data >>= 4;
92
MSB = (data & 0xf) << 4;
93
data >>= 8;
94
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
95
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
96
#undef MSB
97
#undef LSB
98
width -= 2;
99
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
36
index XXXXXXX..XXXXXXX 100644
100
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/misc/unimp.c
101
--- a/hw/display/pl110.c
38
+++ b/hw/misc/unimp.c
102
+++ b/hw/display/pl110.c
39
@@ -XXX,XX +XXX,XX @@
103
@@ -XXX,XX +XXX,XX @@ static const unsigned char *idregs[] = {
40
#include "qemu/log.h"
104
pl111_id
41
#include "qapi/error.h"
105
};
42
106
43
-#define UNIMPLEMENTED_DEVICE(obj) \
107
-#define BITS 32
44
- OBJECT_CHECK(UnimplementedDeviceState, (obj), TYPE_UNIMPLEMENTED_DEVICE)
108
#define COPY_PIXEL(to, from) do { *(uint32_t *)to = from; to += 4; } while (0)
45
-
109
46
-typedef struct {
110
#undef RGB
47
- SysBusDevice parent_obj;
111
@@ -XXX,XX +XXX,XX @@ static const unsigned char *idregs[] = {
48
- MemoryRegion iomem;
112
#include "pl110_template.h"
49
- char *name;
113
#undef BORDER
50
- uint64_t size;
114
51
-} UnimplementedDeviceState;
115
-static drawfn pl110_draw_fn_32[48] = {
52
-
116
- pl110_draw_line1_lblp_bgr32,
53
static uint64_t unimp_read(void *opaque, hwaddr offset, unsigned size)
117
- pl110_draw_line2_lblp_bgr32,
118
- pl110_draw_line4_lblp_bgr32,
119
- pl110_draw_line8_lblp_bgr32,
120
- pl110_draw_line16_555_lblp_bgr32,
121
- pl110_draw_line32_lblp_bgr32,
122
- pl110_draw_line16_lblp_bgr32,
123
- pl110_draw_line12_lblp_bgr32,
124
-
125
- pl110_draw_line1_bbbp_bgr32,
126
- pl110_draw_line2_bbbp_bgr32,
127
- pl110_draw_line4_bbbp_bgr32,
128
- pl110_draw_line8_bbbp_bgr32,
129
- pl110_draw_line16_555_bbbp_bgr32,
130
- pl110_draw_line32_bbbp_bgr32,
131
- pl110_draw_line16_bbbp_bgr32,
132
- pl110_draw_line12_bbbp_bgr32,
133
-
134
- pl110_draw_line1_lbbp_bgr32,
135
- pl110_draw_line2_lbbp_bgr32,
136
- pl110_draw_line4_lbbp_bgr32,
137
- pl110_draw_line8_lbbp_bgr32,
138
- pl110_draw_line16_555_lbbp_bgr32,
139
- pl110_draw_line32_lbbp_bgr32,
140
- pl110_draw_line16_lbbp_bgr32,
141
- pl110_draw_line12_lbbp_bgr32,
142
-
143
- pl110_draw_line1_lblp_rgb32,
144
- pl110_draw_line2_lblp_rgb32,
145
- pl110_draw_line4_lblp_rgb32,
146
- pl110_draw_line8_lblp_rgb32,
147
- pl110_draw_line16_555_lblp_rgb32,
148
- pl110_draw_line32_lblp_rgb32,
149
- pl110_draw_line16_lblp_rgb32,
150
- pl110_draw_line12_lblp_rgb32,
151
-
152
- pl110_draw_line1_bbbp_rgb32,
153
- pl110_draw_line2_bbbp_rgb32,
154
- pl110_draw_line4_bbbp_rgb32,
155
- pl110_draw_line8_bbbp_rgb32,
156
- pl110_draw_line16_555_bbbp_rgb32,
157
- pl110_draw_line32_bbbp_rgb32,
158
- pl110_draw_line16_bbbp_rgb32,
159
- pl110_draw_line12_bbbp_rgb32,
160
-
161
- pl110_draw_line1_lbbp_rgb32,
162
- pl110_draw_line2_lbbp_rgb32,
163
- pl110_draw_line4_lbbp_rgb32,
164
- pl110_draw_line8_lbbp_rgb32,
165
- pl110_draw_line16_555_lbbp_rgb32,
166
- pl110_draw_line32_lbbp_rgb32,
167
- pl110_draw_line16_lbbp_rgb32,
168
- pl110_draw_line12_lbbp_rgb32,
169
-};
170
-
171
-#undef BITS
172
#undef COPY_PIXEL
173
174
+static drawfn pl110_draw_fn_32[48] = {
175
+ pl110_draw_line1_lblp_bgr,
176
+ pl110_draw_line2_lblp_bgr,
177
+ pl110_draw_line4_lblp_bgr,
178
+ pl110_draw_line8_lblp_bgr,
179
+ pl110_draw_line16_555_lblp_bgr,
180
+ pl110_draw_line32_lblp_bgr,
181
+ pl110_draw_line16_lblp_bgr,
182
+ pl110_draw_line12_lblp_bgr,
183
+
184
+ pl110_draw_line1_bbbp_bgr,
185
+ pl110_draw_line2_bbbp_bgr,
186
+ pl110_draw_line4_bbbp_bgr,
187
+ pl110_draw_line8_bbbp_bgr,
188
+ pl110_draw_line16_555_bbbp_bgr,
189
+ pl110_draw_line32_bbbp_bgr,
190
+ pl110_draw_line16_bbbp_bgr,
191
+ pl110_draw_line12_bbbp_bgr,
192
+
193
+ pl110_draw_line1_lbbp_bgr,
194
+ pl110_draw_line2_lbbp_bgr,
195
+ pl110_draw_line4_lbbp_bgr,
196
+ pl110_draw_line8_lbbp_bgr,
197
+ pl110_draw_line16_555_lbbp_bgr,
198
+ pl110_draw_line32_lbbp_bgr,
199
+ pl110_draw_line16_lbbp_bgr,
200
+ pl110_draw_line12_lbbp_bgr,
201
+
202
+ pl110_draw_line1_lblp_rgb,
203
+ pl110_draw_line2_lblp_rgb,
204
+ pl110_draw_line4_lblp_rgb,
205
+ pl110_draw_line8_lblp_rgb,
206
+ pl110_draw_line16_555_lblp_rgb,
207
+ pl110_draw_line32_lblp_rgb,
208
+ pl110_draw_line16_lblp_rgb,
209
+ pl110_draw_line12_lblp_rgb,
210
+
211
+ pl110_draw_line1_bbbp_rgb,
212
+ pl110_draw_line2_bbbp_rgb,
213
+ pl110_draw_line4_bbbp_rgb,
214
+ pl110_draw_line8_bbbp_rgb,
215
+ pl110_draw_line16_555_bbbp_rgb,
216
+ pl110_draw_line32_bbbp_rgb,
217
+ pl110_draw_line16_bbbp_rgb,
218
+ pl110_draw_line12_bbbp_rgb,
219
+
220
+ pl110_draw_line1_lbbp_rgb,
221
+ pl110_draw_line2_lbbp_rgb,
222
+ pl110_draw_line4_lbbp_rgb,
223
+ pl110_draw_line8_lbbp_rgb,
224
+ pl110_draw_line16_555_lbbp_rgb,
225
+ pl110_draw_line32_lbbp_rgb,
226
+ pl110_draw_line16_lbbp_rgb,
227
+ pl110_draw_line12_lbbp_rgb,
228
+};
229
230
static int pl110_enabled(PL110State *s)
54
{
231
{
55
UnimplementedDeviceState *s = UNIMPLEMENTED_DEVICE(opaque);
56
--
232
--
57
2.16.2
233
2.20.1
58
234
59
235
diff view generated by jsdifflib
1
Add a Cortex-M33 definition. The M33 is an M profile CPU
1
For a long time now the UI layer has guaranteed that the console
2
which implements the ARM v8M architecture, including the
2
surface is always 32 bits per pixel. Remove the legacy dead code
3
M profile Security Extension.
3
from the pxa2xx_lcd display device which was handling the possibility
4
that the console surface was some other format.
4
5
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
7
Message-id: 20180220180325.29818-9-peter.maydell@linaro.org
8
Message-id: 20210211141515.8755-5-peter.maydell@linaro.org
8
---
9
---
9
target/arm/cpu.c | 31 +++++++++++++++++++++++++++++++
10
hw/display/pxa2xx_lcd.c | 79 +++++++++--------------------------------
10
1 file changed, 31 insertions(+)
11
1 file changed, 17 insertions(+), 62 deletions(-)
11
12
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c
13
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
15
--- a/hw/display/pxa2xx_lcd.c
15
+++ b/target/arm/cpu.c
16
+++ b/hw/display/pxa2xx_lcd.c
16
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
17
@@ -XXX,XX +XXX,XX @@ struct PXA2xxLCDState {
17
cpu->id_isar5 = 0x00000000;
18
19
int invalidated;
20
QemuConsole *con;
21
- drawfn *line_fn[2];
22
int dest_width;
23
int xres, yres;
24
int pal_for;
25
@@ -XXX,XX +XXX,XX @@ typedef struct QEMU_PACKED {
26
#define LDCMD_SOFINT    (1 << 22)
27
#define LDCMD_PAL    (1 << 26)
28
29
+#define BITS 32
30
+#include "pxa2xx_template.h"
31
+
32
/* Route internal interrupt lines to the global IC */
33
static void pxa2xx_lcdc_int_update(PXA2xxLCDState *s)
34
{
35
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
36
}
18
}
37
}
19
38
20
+static void cortex_m33_initfn(Object *obj)
39
+static inline drawfn pxa2xx_drawfn(PXA2xxLCDState *s)
21
+{
40
+{
22
+ ARMCPU *cpu = ARM_CPU(obj);
41
+ if (s->transp) {
23
+
42
+ return pxa2xx_draw_fn_32t[s->bpp];
24
+ set_feature(&cpu->env, ARM_FEATURE_V8);
43
+ } else {
25
+ set_feature(&cpu->env, ARM_FEATURE_M);
44
+ return pxa2xx_draw_fn_32[s->bpp];
26
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
45
+ }
27
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
28
+ cpu->midr = 0x410fd213; /* r0p3 */
29
+ cpu->pmsav7_dregion = 16;
30
+ cpu->sau_sregion = 8;
31
+ cpu->id_pfr0 = 0x00000030;
32
+ cpu->id_pfr1 = 0x00000210;
33
+ cpu->id_dfr0 = 0x00200000;
34
+ cpu->id_afr0 = 0x00000000;
35
+ cpu->id_mmfr0 = 0x00101F40;
36
+ cpu->id_mmfr1 = 0x00000000;
37
+ cpu->id_mmfr2 = 0x01000000;
38
+ cpu->id_mmfr3 = 0x00000000;
39
+ cpu->id_isar0 = 0x01101110;
40
+ cpu->id_isar1 = 0x02212000;
41
+ cpu->id_isar2 = 0x20232232;
42
+ cpu->id_isar3 = 0x01111131;
43
+ cpu->id_isar4 = 0x01310132;
44
+ cpu->id_isar5 = 0x00000000;
45
+ cpu->clidr = 0x00000000;
46
+ cpu->ctr = 0x8000c000;
47
+}
46
+}
48
+
47
+
49
static void arm_v7m_class_init(ObjectClass *oc, void *data)
48
static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
49
hwaddr addr, int *miny, int *maxy)
50
{
50
{
51
CPUClass *cc = CPU_CLASS(oc);
51
DisplaySurface *surface = qemu_console_surface(s->con);
52
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_cpus[] = {
52
int src_width, dest_width;
53
.class_init = arm_v7m_class_init },
53
- drawfn fn = NULL;
54
{ .name = "cortex-m4", .initfn = cortex_m4_initfn,
54
- if (s->dest_width)
55
.class_init = arm_v7m_class_init },
55
- fn = s->line_fn[s->transp][s->bpp];
56
+ { .name = "cortex-m33", .initfn = cortex_m33_initfn,
56
+ drawfn fn = pxa2xx_drawfn(s);
57
+ .class_init = arm_v7m_class_init },
57
if (!fn)
58
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
58
return;
59
{ .name = "cortex-a7", .initfn = cortex_a7_initfn },
59
60
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
60
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
61
{
62
DisplaySurface *surface = qemu_console_surface(s->con);
63
int src_width, dest_width;
64
- drawfn fn = NULL;
65
- if (s->dest_width)
66
- fn = s->line_fn[s->transp][s->bpp];
67
+ drawfn fn = pxa2xx_drawfn(s);
68
if (!fn)
69
return;
70
71
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
72
{
73
DisplaySurface *surface = qemu_console_surface(s->con);
74
int src_width, dest_width;
75
- drawfn fn = NULL;
76
- if (s->dest_width) {
77
- fn = s->line_fn[s->transp][s->bpp];
78
- }
79
+ drawfn fn = pxa2xx_drawfn(s);
80
if (!fn) {
81
return;
82
}
83
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
84
{
85
DisplaySurface *surface = qemu_console_surface(s->con);
86
int src_width, dest_width;
87
- drawfn fn = NULL;
88
- if (s->dest_width) {
89
- fn = s->line_fn[s->transp][s->bpp];
90
- }
91
+ drawfn fn = pxa2xx_drawfn(s);
92
if (!fn) {
93
return;
94
}
95
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pxa2xx_lcdc = {
96
}
97
};
98
99
-#define BITS 8
100
-#include "pxa2xx_template.h"
101
-#define BITS 15
102
-#include "pxa2xx_template.h"
103
-#define BITS 16
104
-#include "pxa2xx_template.h"
105
-#define BITS 24
106
-#include "pxa2xx_template.h"
107
-#define BITS 32
108
-#include "pxa2xx_template.h"
109
-
110
static const GraphicHwOps pxa2xx_ops = {
111
.invalidate = pxa2xx_invalidate_display,
112
.gfx_update = pxa2xx_update_display,
113
@@ -XXX,XX +XXX,XX @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
114
hwaddr base, qemu_irq irq)
115
{
116
PXA2xxLCDState *s;
117
- DisplaySurface *surface;
118
119
s = (PXA2xxLCDState *) g_malloc0(sizeof(PXA2xxLCDState));
120
s->invalidated = 1;
121
@@ -XXX,XX +XXX,XX @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
122
memory_region_add_subregion(sysmem, base, &s->iomem);
123
124
s->con = graphic_console_init(NULL, 0, &pxa2xx_ops, s);
125
- surface = qemu_console_surface(s->con);
126
-
127
- switch (surface_bits_per_pixel(surface)) {
128
- case 0:
129
- s->dest_width = 0;
130
- break;
131
- case 8:
132
- s->line_fn[0] = pxa2xx_draw_fn_8;
133
- s->line_fn[1] = pxa2xx_draw_fn_8t;
134
- s->dest_width = 1;
135
- break;
136
- case 15:
137
- s->line_fn[0] = pxa2xx_draw_fn_15;
138
- s->line_fn[1] = pxa2xx_draw_fn_15t;
139
- s->dest_width = 2;
140
- break;
141
- case 16:
142
- s->line_fn[0] = pxa2xx_draw_fn_16;
143
- s->line_fn[1] = pxa2xx_draw_fn_16t;
144
- s->dest_width = 2;
145
- break;
146
- case 24:
147
- s->line_fn[0] = pxa2xx_draw_fn_24;
148
- s->line_fn[1] = pxa2xx_draw_fn_24t;
149
- s->dest_width = 3;
150
- break;
151
- case 32:
152
- s->line_fn[0] = pxa2xx_draw_fn_32;
153
- s->line_fn[1] = pxa2xx_draw_fn_32t;
154
- s->dest_width = 4;
155
- break;
156
- default:
157
- fprintf(stderr, "%s: Bad color depth\n", __func__);
158
- exit(1);
159
- }
160
+ s->dest_width = 4;
161
162
vmstate_register(NULL, 0, &vmstate_pxa2xx_lcdc, s);
163
61
--
164
--
62
2.16.2
165
2.20.1
63
166
64
167
diff view generated by jsdifflib
1
Create an "init-svtor" property on the armv7m container
1
Since the dest_width is now always 4 because the output surface is
2
object which we can forward to the CPU object.
2
32bpp, we can replace the dest_width state field with a constant.
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
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
6
Message-id: 20180220180325.29818-8-peter.maydell@linaro.org
6
Message-id: 20210211141515.8755-6-peter.maydell@linaro.org
7
---
7
---
8
include/hw/arm/armv7m.h | 2 ++
8
hw/display/pxa2xx_lcd.c | 20 +++++++++++---------
9
hw/arm/armv7m.c | 9 +++++++++
9
1 file changed, 11 insertions(+), 9 deletions(-)
10
2 files changed, 11 insertions(+)
11
10
12
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
11
diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c
13
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/armv7m.h
13
--- a/hw/display/pxa2xx_lcd.c
15
+++ b/include/hw/arm/armv7m.h
14
+++ b/hw/display/pxa2xx_lcd.c
16
@@ -XXX,XX +XXX,XX @@ typedef struct {
15
@@ -XXX,XX +XXX,XX @@ typedef struct QEMU_PACKED {
17
* that CPU accesses see. (The NVIC, bitbanding and other CPU-internal
16
#define LDCMD_SOFINT    (1 << 22)
18
* devices will be automatically layered on top of this view.)
17
#define LDCMD_PAL    (1 << 26)
19
* + Property "idau": IDAU interface (forwarded to CPU object)
18
20
+ * + Property "init-svtor": secure VTOR reset value (forwarded to CPU object)
19
+/* Size of a pixel in the QEMU UI output surface, in bytes */
21
*/
20
+#define DEST_PIXEL_WIDTH 4
22
typedef struct ARMv7MState {
21
+
23
/*< private >*/
22
#define BITS 32
24
@@ -XXX,XX +XXX,XX @@ typedef struct ARMv7MState {
23
#include "pxa2xx_template.h"
25
/* MemoryRegion the board provides to us (with its devices, RAM, etc) */
24
26
MemoryRegion *board_memory;
25
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
27
Object *idau;
26
else if (s->bpp > pxa_lcdc_8bpp)
28
+ uint32_t init_svtor;
27
src_width *= 2;
29
} ARMv7MState;
28
30
29
- dest_width = s->xres * s->dest_width;
31
#endif
30
+ dest_width = s->xres * DEST_PIXEL_WIDTH;
32
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
31
*miny = 0;
33
index XXXXXXX..XXXXXXX 100644
32
if (s->invalidated) {
34
--- a/hw/arm/armv7m.c
33
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
35
+++ b/hw/arm/armv7m.c
34
addr, s->yres, src_width);
36
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
37
return;
38
}
39
}
35
}
40
+ if (object_property_find(OBJECT(s->cpu), "init-svtor", NULL)) {
36
framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
41
+ object_property_set_uint(OBJECT(s->cpu), s->init_svtor,
37
- src_width, dest_width, s->dest_width,
42
+ "init-svtor", &err);
38
+ src_width, dest_width, DEST_PIXEL_WIDTH,
43
+ if (err != NULL) {
39
s->invalidated,
44
+ error_propagate(errp, err);
40
fn, s->dma_ch[0].palette, miny, maxy);
45
+ return;
41
}
46
+ }
42
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
47
+ }
43
else if (s->bpp > pxa_lcdc_8bpp)
48
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
44
src_width *= 2;
49
if (err != NULL) {
45
50
error_propagate(errp, err);
46
- dest_width = s->yres * s->dest_width;
51
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
47
+ dest_width = s->yres * DEST_PIXEL_WIDTH;
52
DEFINE_PROP_LINK("memory", ARMv7MState, board_memory, TYPE_MEMORY_REGION,
48
*miny = 0;
53
MemoryRegion *),
49
if (s->invalidated) {
54
DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
50
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
55
+ DEFINE_PROP_UINT32("init-svtor", ARMv7MState, init_svtor, 0),
51
addr, s->yres, src_width);
56
DEFINE_PROP_END_OF_LIST(),
52
}
57
};
53
framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
54
- src_width, s->dest_width, -dest_width,
55
+ src_width, DEST_PIXEL_WIDTH, -dest_width,
56
s->invalidated,
57
fn, s->dma_ch[0].palette,
58
miny, maxy);
59
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
60
src_width *= 2;
61
}
62
63
- dest_width = s->xres * s->dest_width;
64
+ dest_width = s->xres * DEST_PIXEL_WIDTH;
65
*miny = 0;
66
if (s->invalidated) {
67
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
68
addr, s->yres, src_width);
69
}
70
framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
71
- src_width, -dest_width, -s->dest_width,
72
+ src_width, -dest_width, -DEST_PIXEL_WIDTH,
73
s->invalidated,
74
fn, s->dma_ch[0].palette, miny, maxy);
75
}
76
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
77
src_width *= 2;
78
}
79
80
- dest_width = s->yres * s->dest_width;
81
+ dest_width = s->yres * DEST_PIXEL_WIDTH;
82
*miny = 0;
83
if (s->invalidated) {
84
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
85
addr, s->yres, src_width);
86
}
87
framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
88
- src_width, -s->dest_width, dest_width,
89
+ src_width, -DEST_PIXEL_WIDTH, dest_width,
90
s->invalidated,
91
fn, s->dma_ch[0].palette,
92
miny, maxy);
93
@@ -XXX,XX +XXX,XX @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
94
memory_region_add_subregion(sysmem, base, &s->iomem);
95
96
s->con = graphic_console_init(NULL, 0, &pxa2xx_ops, s);
97
- s->dest_width = 4;
98
99
vmstate_register(NULL, 0, &vmstate_pxa2xx_lcdc, s);
58
100
59
--
101
--
60
2.16.2
102
2.20.1
61
103
62
104
diff view generated by jsdifflib
1
The IoTKit Security Controller includes various registers
1
Now that BITS is always 32, expand out all its uses in the template
2
that expose to software the controls for the Peripheral
2
header, including removing now-useless uses of the glue() macro.
3
Protection Controllers in the system. Implement these.
4
3
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
7
Message-id: 20180220180325.29818-17-peter.maydell@linaro.org
6
Message-id: 20210211141515.8755-7-peter.maydell@linaro.org
8
---
7
---
9
include/hw/misc/iotkit-secctl.h | 64 +++++++++-
8
hw/display/pxa2xx_template.h | 110 ++++++++++++++---------------------
10
hw/misc/iotkit-secctl.c | 270 +++++++++++++++++++++++++++++++++++++---
9
1 file changed, 45 insertions(+), 65 deletions(-)
11
2 files changed, 315 insertions(+), 19 deletions(-)
12
10
13
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
11
diff --git a/hw/display/pxa2xx_template.h b/hw/display/pxa2xx_template.h
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/misc/iotkit-secctl.h
13
--- a/hw/display/pxa2xx_template.h
16
+++ b/include/hw/misc/iotkit-secctl.h
14
+++ b/hw/display/pxa2xx_template.h
17
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@
18
* QEMU interface:
19
* + sysbus MMIO region 0 is the "secure privilege control block" registers
20
* + sysbus MMIO region 1 is the "non-secure privilege control block" registers
21
+ * + named GPIO output "sec_resp_cfg" indicating whether blocked accesses
22
+ * should RAZ/WI or bus error
23
+ * Controlling the 2 APB PPCs in the IoTKit:
24
+ * + named GPIO outputs apb_ppc0_nonsec[0..2] and apb_ppc1_nonsec
25
+ * + named GPIO outputs apb_ppc0_ap[0..2] and apb_ppc1_ap
26
+ * + named GPIO outputs apb_ppc{0,1}_irq_enable
27
+ * + named GPIO outputs apb_ppc{0,1}_irq_clear
28
+ * + named GPIO inputs apb_ppc{0,1}_irq_status
29
+ * Controlling each of the 4 expansion APB PPCs which a system using the IoTKit
30
+ * might provide:
31
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15]
32
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_ap[0..15]
33
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_enable
34
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_clear
35
+ * + named GPIO inputs apb_ppcexp{0,1,2,3}_irq_status
36
+ * Controlling each of the 4 expansion AHB PPCs which a system using the IoTKit
37
+ * might provide:
38
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_nonsec[0..15]
39
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_ap[0..15]
40
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
41
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
42
+ * + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
43
*/
16
*/
44
17
45
#ifndef IOTKIT_SECCTL_H
18
# define SKIP_PIXEL(to)        to += deststep
19
-#if BITS == 8
20
-# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0)
21
-#elif BITS == 15 || BITS == 16
22
-# define COPY_PIXEL(to, from) \
23
- do { \
24
- *(uint16_t *) to = from; \
25
- SKIP_PIXEL(to); \
26
- } while (0)
27
-#elif BITS == 24
28
-# define COPY_PIXEL(to, from) \
29
- do { \
30
- *(uint16_t *) to = from; \
31
- *(to + 2) = (from) >> 16; \
32
- SKIP_PIXEL(to); \
33
- } while (0)
34
-#elif BITS == 32
35
# define COPY_PIXEL(to, from) \
36
do { \
37
*(uint32_t *) to = from; \
38
SKIP_PIXEL(to); \
39
} while (0)
40
-#else
41
-# error unknown bit depth
42
-#endif
43
44
#ifdef HOST_WORDS_BIGENDIAN
45
# define SWAP_WORDS    1
46
@@ -XXX,XX +XXX,XX @@
46
@@ -XXX,XX +XXX,XX @@
47
#define TYPE_IOTKIT_SECCTL "iotkit-secctl"
47
#define FN_2(x)        FN(x + 1) FN(x)
48
#define IOTKIT_SECCTL(obj) OBJECT_CHECK(IoTKitSecCtl, (obj), TYPE_IOTKIT_SECCTL)
48
#define FN_4(x)        FN_2(x + 2) FN_2(x)
49
49
50
-typedef struct IoTKitSecCtl {
50
-static void glue(pxa2xx_draw_line2_, BITS)(void *opaque,
51
+#define IOTS_APB_PPC0_NUM_PORTS 3
51
+static void pxa2xx_draw_line2(void *opaque,
52
+#define IOTS_APB_PPC1_NUM_PORTS 1
52
uint8_t *dest, const uint8_t *src, int width, int deststep)
53
+#define IOTS_PPC_NUM_PORTS 16
53
{
54
+#define IOTS_NUM_APB_PPC 2
54
uint32_t *palette = opaque;
55
+#define IOTS_NUM_APB_EXP_PPC 4
55
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line2_, BITS)(void *opaque,
56
+#define IOTS_NUM_AHB_EXP_PPC 4
56
}
57
+
57
}
58
+typedef struct IoTKitSecCtl IoTKitSecCtl;
58
59
+
59
-static void glue(pxa2xx_draw_line4_, BITS)(void *opaque,
60
+/* State and IRQ lines relating to a PPC. For the
60
+static void pxa2xx_draw_line4(void *opaque,
61
+ * PPCs in the IoTKit not all the IRQ lines are used.
61
uint8_t *dest, const uint8_t *src, int width, int deststep)
62
+ */
62
{
63
+typedef struct IoTKitSecCtlPPC {
63
uint32_t *palette = opaque;
64
+ qemu_irq nonsec[IOTS_PPC_NUM_PORTS];
64
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line4_, BITS)(void *opaque,
65
+ qemu_irq ap[IOTS_PPC_NUM_PORTS];
65
}
66
+ qemu_irq irq_enable;
66
}
67
+ qemu_irq irq_clear;
67
68
+
68
-static void glue(pxa2xx_draw_line8_, BITS)(void *opaque,
69
+ uint32_t ns;
69
+static void pxa2xx_draw_line8(void *opaque,
70
+ uint32_t sp;
70
uint8_t *dest, const uint8_t *src, int width, int deststep)
71
+ uint32_t nsp;
71
{
72
+
72
uint32_t *palette = opaque;
73
+ /* Number of ports actually present */
73
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line8_, BITS)(void *opaque,
74
+ int numports;
74
}
75
+ /* Offset of this PPC's interrupt bits in SECPPCINTSTAT */
75
}
76
+ int irq_bit_offset;
76
77
+ IoTKitSecCtl *parent;
77
-static void glue(pxa2xx_draw_line16_, BITS)(void *opaque,
78
+} IoTKitSecCtlPPC;
78
+static void pxa2xx_draw_line16(void *opaque,
79
+
79
uint8_t *dest, const uint8_t *src, int width, int deststep)
80
+struct IoTKitSecCtl {
80
{
81
/*< private >*/
81
uint32_t data;
82
SysBusDevice parent_obj;
82
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line16_, BITS)(void *opaque,
83
83
data >>= 6;
84
/*< public >*/
84
r = (data & 0x1f) << 3;
85
+ qemu_irq sec_resp_cfg;
85
data >>= 5;
86
86
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
87
MemoryRegion s_regs;
87
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
88
MemoryRegion ns_regs;
88
b = (data & 0x1f) << 3;
89
-} IoTKitSecCtl;
89
data >>= 5;
90
+
90
g = (data & 0x3f) << 2;
91
+ uint32_t secppcintstat;
91
data >>= 6;
92
+ uint32_t secppcinten;
92
r = (data & 0x1f) << 3;
93
+ uint32_t secrespcfg;
93
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
94
+
94
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
95
+ IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
95
width -= 2;
96
+ IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
96
src += 4;
97
+ IoTKitSecCtlPPC ahbexp[IOTS_NUM_APB_EXP_PPC];
97
}
98
+};
98
}
99
99
100
#endif
100
-static void glue(pxa2xx_draw_line16t_, BITS)(void *opaque,
101
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
101
+static void pxa2xx_draw_line16t(void *opaque,
102
index XXXXXXX..XXXXXXX 100644
102
uint8_t *dest, const uint8_t *src, int width, int deststep)
103
--- a/hw/misc/iotkit-secctl.c
103
{
104
+++ b/hw/misc/iotkit-secctl.c
104
uint32_t data;
105
@@ -XXX,XX +XXX,XX @@ static const uint8_t iotkit_secctl_ns_idregs[] = {
105
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line16t_, BITS)(void *opaque,
106
0x0d, 0xf0, 0x05, 0xb1,
106
if (data & 1)
107
SKIP_PIXEL(dest);
108
else
109
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
110
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
111
data >>= 1;
112
b = (data & 0x1f) << 3;
113
data >>= 5;
114
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line16t_, BITS)(void *opaque,
115
if (data & 1)
116
SKIP_PIXEL(dest);
117
else
118
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
119
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
120
width -= 2;
121
src += 4;
122
}
123
}
124
125
-static void glue(pxa2xx_draw_line18_, BITS)(void *opaque,
126
+static void pxa2xx_draw_line18(void *opaque,
127
uint8_t *dest, const uint8_t *src, int width, int deststep)
128
{
129
uint32_t data;
130
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line18_, BITS)(void *opaque,
131
g = (data & 0x3f) << 2;
132
data >>= 6;
133
r = (data & 0x3f) << 2;
134
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
135
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
136
width -= 1;
137
src += 4;
138
}
139
}
140
141
/* The wicked packed format */
142
-static void glue(pxa2xx_draw_line18p_, BITS)(void *opaque,
143
+static void pxa2xx_draw_line18p(void *opaque,
144
uint8_t *dest, const uint8_t *src, int width, int deststep)
145
{
146
uint32_t data[3];
147
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line18p_, BITS)(void *opaque,
148
data[0] >>= 6;
149
r = (data[0] & 0x3f) << 2;
150
data[0] >>= 12;
151
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
152
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
153
b = (data[0] & 0x3f) << 2;
154
data[0] >>= 6;
155
g = ((data[1] & 0xf) << 4) | (data[0] << 2);
156
data[1] >>= 4;
157
r = (data[1] & 0x3f) << 2;
158
data[1] >>= 12;
159
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
160
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
161
b = (data[1] & 0x3f) << 2;
162
data[1] >>= 6;
163
g = (data[1] & 0x3f) << 2;
164
data[1] >>= 6;
165
r = ((data[2] & 0x3) << 6) | (data[1] << 2);
166
data[2] >>= 8;
167
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
168
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
169
b = (data[2] & 0x3f) << 2;
170
data[2] >>= 6;
171
g = (data[2] & 0x3f) << 2;
172
data[2] >>= 6;
173
r = data[2] << 2;
174
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
175
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
176
width -= 4;
177
}
178
}
179
180
-static void glue(pxa2xx_draw_line19_, BITS)(void *opaque,
181
+static void pxa2xx_draw_line19(void *opaque,
182
uint8_t *dest, const uint8_t *src, int width, int deststep)
183
{
184
uint32_t data;
185
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line19_, BITS)(void *opaque,
186
if (data & 1)
187
SKIP_PIXEL(dest);
188
else
189
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
190
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
191
width -= 1;
192
src += 4;
193
}
194
}
195
196
/* The wicked packed format */
197
-static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque,
198
+static void pxa2xx_draw_line19p(void *opaque,
199
uint8_t *dest, const uint8_t *src, int width, int deststep)
200
{
201
uint32_t data[3];
202
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque,
203
if (data[0] & 1)
204
SKIP_PIXEL(dest);
205
else
206
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
207
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
208
data[0] >>= 6;
209
b = (data[0] & 0x3f) << 2;
210
data[0] >>= 6;
211
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque,
212
if (data[1] & 1)
213
SKIP_PIXEL(dest);
214
else
215
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
216
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
217
data[1] >>= 6;
218
b = (data[1] & 0x3f) << 2;
219
data[1] >>= 6;
220
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque,
221
if (data[2] & 1)
222
SKIP_PIXEL(dest);
223
else
224
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
225
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
226
data[2] >>= 6;
227
b = (data[2] & 0x3f) << 2;
228
data[2] >>= 6;
229
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque,
230
if (data[2] & 1)
231
SKIP_PIXEL(dest);
232
else
233
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
234
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
235
width -= 4;
236
}
237
}
238
239
-static void glue(pxa2xx_draw_line24_, BITS)(void *opaque,
240
+static void pxa2xx_draw_line24(void *opaque,
241
uint8_t *dest, const uint8_t *src, int width, int deststep)
242
{
243
uint32_t data;
244
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line24_, BITS)(void *opaque,
245
g = data & 0xff;
246
data >>= 8;
247
r = data & 0xff;
248
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
249
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
250
width -= 1;
251
src += 4;
252
}
253
}
254
255
-static void glue(pxa2xx_draw_line24t_, BITS)(void *opaque,
256
+static void pxa2xx_draw_line24t(void *opaque,
257
uint8_t *dest, const uint8_t *src, int width, int deststep)
258
{
259
uint32_t data;
260
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line24t_, BITS)(void *opaque,
261
if (data & 1)
262
SKIP_PIXEL(dest);
263
else
264
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
265
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
266
width -= 1;
267
src += 4;
268
}
269
}
270
271
-static void glue(pxa2xx_draw_line25_, BITS)(void *opaque,
272
+static void pxa2xx_draw_line25(void *opaque,
273
uint8_t *dest, const uint8_t *src, int width, int deststep)
274
{
275
uint32_t data;
276
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line25_, BITS)(void *opaque,
277
if (data & 1)
278
SKIP_PIXEL(dest);
279
else
280
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
281
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
282
width -= 1;
283
src += 4;
284
}
285
}
286
287
/* Overlay planes disabled, no transparency */
288
-static drawfn glue(pxa2xx_draw_fn_, BITS)[16] =
289
+static drawfn pxa2xx_draw_fn_32[16] =
290
{
291
[0 ... 0xf] = NULL,
292
- [pxa_lcdc_2bpp] = glue(pxa2xx_draw_line2_, BITS),
293
- [pxa_lcdc_4bpp] = glue(pxa2xx_draw_line4_, BITS),
294
- [pxa_lcdc_8bpp] = glue(pxa2xx_draw_line8_, BITS),
295
- [pxa_lcdc_16bpp] = glue(pxa2xx_draw_line16_, BITS),
296
- [pxa_lcdc_18bpp] = glue(pxa2xx_draw_line18_, BITS),
297
- [pxa_lcdc_18pbpp] = glue(pxa2xx_draw_line18p_, BITS),
298
- [pxa_lcdc_24bpp] = glue(pxa2xx_draw_line24_, BITS),
299
+ [pxa_lcdc_2bpp] = pxa2xx_draw_line2,
300
+ [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
301
+ [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
302
+ [pxa_lcdc_16bpp] = pxa2xx_draw_line16,
303
+ [pxa_lcdc_18bpp] = pxa2xx_draw_line18,
304
+ [pxa_lcdc_18pbpp] = pxa2xx_draw_line18p,
305
+ [pxa_lcdc_24bpp] = pxa2xx_draw_line24,
107
};
306
};
108
307
109
+/* The register sets for the various PPCs (AHB internal, APB internal,
308
/* Overlay planes enabled, transparency used */
110
+ * AHB expansion, APB expansion) are all set up so that they are
309
-static drawfn glue(glue(pxa2xx_draw_fn_, BITS), t)[16] =
111
+ * in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs
310
+static drawfn pxa2xx_draw_fn_32t[16] =
112
+ * 0, 1, 2, 3 of that type, so we can convert a register address offset
311
{
113
+ * into an an index into a PPC array easily.
312
[0 ... 0xf] = NULL,
114
+ */
313
- [pxa_lcdc_4bpp] = glue(pxa2xx_draw_line4_, BITS),
115
+static inline int offset_to_ppc_idx(uint32_t offset)
314
- [pxa_lcdc_8bpp] = glue(pxa2xx_draw_line8_, BITS),
116
+{
315
- [pxa_lcdc_16bpp] = glue(pxa2xx_draw_line16t_, BITS),
117
+ return extract32(offset, 2, 2);
316
- [pxa_lcdc_19bpp] = glue(pxa2xx_draw_line19_, BITS),
118
+}
317
- [pxa_lcdc_19pbpp] = glue(pxa2xx_draw_line19p_, BITS),
119
+
318
- [pxa_lcdc_24bpp] = glue(pxa2xx_draw_line24t_, BITS),
120
+typedef void PerPPCFunction(IoTKitSecCtlPPC *ppc);
319
- [pxa_lcdc_25bpp] = glue(pxa2xx_draw_line25_, BITS),
121
+
320
+ [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
122
+static void foreach_ppc(IoTKitSecCtl *s, PerPPCFunction *fn)
321
+ [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
123
+{
322
+ [pxa_lcdc_16bpp] = pxa2xx_draw_line16t,
124
+ int i;
323
+ [pxa_lcdc_19bpp] = pxa2xx_draw_line19,
125
+
324
+ [pxa_lcdc_19pbpp] = pxa2xx_draw_line19p,
126
+ for (i = 0; i < IOTS_NUM_APB_PPC; i++) {
325
+ [pxa_lcdc_24bpp] = pxa2xx_draw_line24t,
127
+ fn(&s->apb[i]);
326
+ [pxa_lcdc_25bpp] = pxa2xx_draw_line25,
128
+ }
129
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
130
+ fn(&s->apbexp[i]);
131
+ }
132
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
133
+ fn(&s->ahbexp[i]);
134
+ }
135
+}
136
+
137
static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
138
uint64_t *pdata,
139
unsigned size, MemTxAttrs attrs)
140
{
141
uint64_t r;
142
uint32_t offset = addr & ~0x3;
143
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
144
145
switch (offset) {
146
case A_AHBNSPPC0:
147
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
148
r = 0;
149
break;
150
case A_SECRESPCFG:
151
- case A_NSCCFG:
152
- case A_SECMPCINTSTATUS:
153
+ r = s->secrespcfg;
154
+ break;
155
case A_SECPPCINTSTAT:
156
+ r = s->secppcintstat;
157
+ break;
158
case A_SECPPCINTEN:
159
- case A_SECMSCINTSTAT:
160
- case A_SECMSCINTEN:
161
- case A_BRGINTSTAT:
162
- case A_BRGINTEN:
163
+ r = s->secppcinten;
164
+ break;
165
case A_AHBNSPPCEXP0:
166
case A_AHBNSPPCEXP1:
167
case A_AHBNSPPCEXP2:
168
case A_AHBNSPPCEXP3:
169
+ r = s->ahbexp[offset_to_ppc_idx(offset)].ns;
170
+ break;
171
case A_APBNSPPC0:
172
case A_APBNSPPC1:
173
+ r = s->apb[offset_to_ppc_idx(offset)].ns;
174
+ break;
175
case A_APBNSPPCEXP0:
176
case A_APBNSPPCEXP1:
177
case A_APBNSPPCEXP2:
178
case A_APBNSPPCEXP3:
179
+ r = s->apbexp[offset_to_ppc_idx(offset)].ns;
180
+ break;
181
case A_AHBSPPPCEXP0:
182
case A_AHBSPPPCEXP1:
183
case A_AHBSPPPCEXP2:
184
case A_AHBSPPPCEXP3:
185
+ r = s->apbexp[offset_to_ppc_idx(offset)].sp;
186
+ break;
187
case A_APBSPPPC0:
188
case A_APBSPPPC1:
189
+ r = s->apb[offset_to_ppc_idx(offset)].sp;
190
+ break;
191
case A_APBSPPPCEXP0:
192
case A_APBSPPPCEXP1:
193
case A_APBSPPPCEXP2:
194
case A_APBSPPPCEXP3:
195
+ r = s->apbexp[offset_to_ppc_idx(offset)].sp;
196
+ break;
197
+ case A_NSCCFG:
198
+ case A_SECMPCINTSTATUS:
199
+ case A_SECMSCINTSTAT:
200
+ case A_SECMSCINTEN:
201
+ case A_BRGINTSTAT:
202
+ case A_BRGINTEN:
203
case A_NSMSCEXP:
204
qemu_log_mask(LOG_UNIMP,
205
"IoTKit SecCtl S block read: "
206
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
207
return MEMTX_OK;
208
}
209
210
+static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC *ppc)
211
+{
212
+ int i;
213
+
214
+ for (i = 0; i < ppc->numports; i++) {
215
+ bool v;
216
+
217
+ if (extract32(ppc->ns, i, 1)) {
218
+ v = extract32(ppc->nsp, i, 1);
219
+ } else {
220
+ v = extract32(ppc->sp, i, 1);
221
+ }
222
+ qemu_set_irq(ppc->ap[i], v);
223
+ }
224
+}
225
+
226
+static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC *ppc, uint32_t value)
227
+{
228
+ int i;
229
+
230
+ ppc->ns = value & MAKE_64BIT_MASK(0, ppc->numports);
231
+ for (i = 0; i < ppc->numports; i++) {
232
+ qemu_set_irq(ppc->nonsec[i], extract32(ppc->ns, i, 1));
233
+ }
234
+ iotkit_secctl_update_ppc_ap(ppc);
235
+}
236
+
237
+static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
238
+{
239
+ ppc->sp = value & MAKE_64BIT_MASK(0, ppc->numports);
240
+ iotkit_secctl_update_ppc_ap(ppc);
241
+}
242
+
243
+static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
244
+{
245
+ ppc->nsp = value & MAKE_64BIT_MASK(0, ppc->numports);
246
+ iotkit_secctl_update_ppc_ap(ppc);
247
+}
248
+
249
+static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC *ppc)
250
+{
251
+ uint32_t value = ppc->parent->secppcintstat;
252
+
253
+ qemu_set_irq(ppc->irq_clear, extract32(value, ppc->irq_bit_offset, 1));
254
+}
255
+
256
+static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc)
257
+{
258
+ uint32_t value = ppc->parent->secppcinten;
259
+
260
+ qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1));
261
+}
262
+
263
static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
264
uint64_t value,
265
unsigned size, MemTxAttrs attrs)
266
{
267
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
268
uint32_t offset = addr;
269
+ IoTKitSecCtlPPC *ppc;
270
271
trace_iotkit_secctl_s_write(offset, value, size);
272
273
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
274
275
switch (offset) {
276
case A_SECRESPCFG:
277
- case A_NSCCFG:
278
+ value &= 1;
279
+ s->secrespcfg = value;
280
+ qemu_set_irq(s->sec_resp_cfg, s->secrespcfg);
281
+ break;
282
case A_SECPPCINTCLR:
283
+ value &= 0x00f000f3;
284
+ foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear);
285
+ break;
286
case A_SECPPCINTEN:
287
- case A_SECMSCINTCLR:
288
- case A_SECMSCINTEN:
289
- case A_BRGINTCLR:
290
- case A_BRGINTEN:
291
+ s->secppcinten = value & 0x00f000f3;
292
+ foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
293
+ break;
294
case A_AHBNSPPCEXP0:
295
case A_AHBNSPPCEXP1:
296
case A_AHBNSPPCEXP2:
297
case A_AHBNSPPCEXP3:
298
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
299
+ iotkit_secctl_ppc_ns_write(ppc, value);
300
+ break;
301
case A_APBNSPPC0:
302
case A_APBNSPPC1:
303
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
304
+ iotkit_secctl_ppc_ns_write(ppc, value);
305
+ break;
306
case A_APBNSPPCEXP0:
307
case A_APBNSPPCEXP1:
308
case A_APBNSPPCEXP2:
309
case A_APBNSPPCEXP3:
310
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
311
+ iotkit_secctl_ppc_ns_write(ppc, value);
312
+ break;
313
case A_AHBSPPPCEXP0:
314
case A_AHBSPPPCEXP1:
315
case A_AHBSPPPCEXP2:
316
case A_AHBSPPPCEXP3:
317
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
318
+ iotkit_secctl_ppc_sp_write(ppc, value);
319
+ break;
320
case A_APBSPPPC0:
321
case A_APBSPPPC1:
322
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
323
+ iotkit_secctl_ppc_sp_write(ppc, value);
324
+ break;
325
case A_APBSPPPCEXP0:
326
case A_APBSPPPCEXP1:
327
case A_APBSPPPCEXP2:
328
case A_APBSPPPCEXP3:
329
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
330
+ iotkit_secctl_ppc_sp_write(ppc, value);
331
+ break;
332
+ case A_NSCCFG:
333
+ case A_SECMSCINTCLR:
334
+ case A_SECMSCINTEN:
335
+ case A_BRGINTCLR:
336
+ case A_BRGINTEN:
337
qemu_log_mask(LOG_UNIMP,
338
"IoTKit SecCtl S block write: "
339
"unimplemented offset 0x%x\n", offset);
340
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
341
uint64_t *pdata,
342
unsigned size, MemTxAttrs attrs)
343
{
344
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
345
uint64_t r;
346
uint32_t offset = addr & ~0x3;
347
348
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
349
case A_AHBNSPPPCEXP1:
350
case A_AHBNSPPPCEXP2:
351
case A_AHBNSPPPCEXP3:
352
+ r = s->ahbexp[offset_to_ppc_idx(offset)].nsp;
353
+ break;
354
case A_APBNSPPPC0:
355
case A_APBNSPPPC1:
356
+ r = s->apb[offset_to_ppc_idx(offset)].nsp;
357
+ break;
358
case A_APBNSPPPCEXP0:
359
case A_APBNSPPPCEXP1:
360
case A_APBNSPPPCEXP2:
361
case A_APBNSPPPCEXP3:
362
- qemu_log_mask(LOG_UNIMP,
363
- "IoTKit SecCtl NS block read: "
364
- "unimplemented offset 0x%x\n", offset);
365
+ r = s->apbexp[offset_to_ppc_idx(offset)].nsp;
366
break;
367
case A_PID4:
368
case A_PID5:
369
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
370
uint64_t value,
371
unsigned size, MemTxAttrs attrs)
372
{
373
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
374
uint32_t offset = addr;
375
+ IoTKitSecCtlPPC *ppc;
376
377
trace_iotkit_secctl_ns_write(offset, value, size);
378
379
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
380
case A_AHBNSPPPCEXP1:
381
case A_AHBNSPPPCEXP2:
382
case A_AHBNSPPPCEXP3:
383
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
384
+ iotkit_secctl_ppc_nsp_write(ppc, value);
385
+ break;
386
case A_APBNSPPPC0:
387
case A_APBNSPPPC1:
388
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
389
+ iotkit_secctl_ppc_nsp_write(ppc, value);
390
+ break;
391
case A_APBNSPPPCEXP0:
392
case A_APBNSPPPCEXP1:
393
case A_APBNSPPPCEXP2:
394
case A_APBNSPPPCEXP3:
395
- qemu_log_mask(LOG_UNIMP,
396
- "IoTKit SecCtl NS block write: "
397
- "unimplemented offset 0x%x\n", offset);
398
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
399
+ iotkit_secctl_ppc_nsp_write(ppc, value);
400
break;
401
case A_AHBNSPPPC0:
402
case A_PID4:
403
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps iotkit_secctl_ns_ops = {
404
.impl.max_access_size = 4,
405
};
327
};
406
328
407
+static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
329
-#undef BITS
408
+{
330
#undef COPY_PIXEL
409
+ ppc->ns = 0;
331
#undef SKIP_PIXEL
410
+ ppc->sp = 0;
332
411
+ ppc->nsp = 0;
412
+}
413
+
414
static void iotkit_secctl_reset(DeviceState *dev)
415
{
416
+ IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
417
418
+ s->secppcintstat = 0;
419
+ s->secppcinten = 0;
420
+ s->secrespcfg = 0;
421
+
422
+ foreach_ppc(s, iotkit_secctl_reset_ppc);
423
+}
424
+
425
+static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
426
+{
427
+ IoTKitSecCtlPPC *ppc = opaque;
428
+ IoTKitSecCtl *s = IOTKIT_SECCTL(ppc->parent);
429
+ int irqbit = ppc->irq_bit_offset + n;
430
+
431
+ s->secppcintstat = deposit32(s->secppcintstat, irqbit, 1, level);
432
+}
433
+
434
+static void iotkit_secctl_init_ppc(IoTKitSecCtl *s,
435
+ IoTKitSecCtlPPC *ppc,
436
+ const char *name,
437
+ int numports,
438
+ int irq_bit_offset)
439
+{
440
+ char *gpioname;
441
+ DeviceState *dev = DEVICE(s);
442
+
443
+ ppc->numports = numports;
444
+ ppc->irq_bit_offset = irq_bit_offset;
445
+ ppc->parent = s;
446
+
447
+ gpioname = g_strdup_printf("%s_nonsec", name);
448
+ qdev_init_gpio_out_named(dev, ppc->nonsec, gpioname, numports);
449
+ g_free(gpioname);
450
+ gpioname = g_strdup_printf("%s_ap", name);
451
+ qdev_init_gpio_out_named(dev, ppc->ap, gpioname, numports);
452
+ g_free(gpioname);
453
+ gpioname = g_strdup_printf("%s_irq_enable", name);
454
+ qdev_init_gpio_out_named(dev, &ppc->irq_enable, gpioname, 1);
455
+ g_free(gpioname);
456
+ gpioname = g_strdup_printf("%s_irq_clear", name);
457
+ qdev_init_gpio_out_named(dev, &ppc->irq_clear, gpioname, 1);
458
+ g_free(gpioname);
459
+ gpioname = g_strdup_printf("%s_irq_status", name);
460
+ qdev_init_gpio_in_named_with_opaque(dev, iotkit_secctl_ppc_irqstatus,
461
+ ppc, gpioname, 1);
462
+ g_free(gpioname);
463
}
464
465
static void iotkit_secctl_init(Object *obj)
466
{
467
IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
468
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
469
+ DeviceState *dev = DEVICE(obj);
470
+ int i;
471
+
472
+ iotkit_secctl_init_ppc(s, &s->apb[0], "apb_ppc0",
473
+ IOTS_APB_PPC0_NUM_PORTS, 0);
474
+ iotkit_secctl_init_ppc(s, &s->apb[1], "apb_ppc1",
475
+ IOTS_APB_PPC1_NUM_PORTS, 1);
476
+
477
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
478
+ IoTKitSecCtlPPC *ppc = &s->apbexp[i];
479
+ char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
480
+ iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 4 + i);
481
+ g_free(ppcname);
482
+ }
483
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
484
+ IoTKitSecCtlPPC *ppc = &s->ahbexp[i];
485
+ char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
486
+ iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 20 + i);
487
+ g_free(ppcname);
488
+ }
489
+
490
+ qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
491
492
memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
493
s, "iotkit-secctl-s-regs", 0x1000);
494
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
495
sysbus_init_mmio(sbd, &s->ns_regs);
496
}
497
498
+static const VMStateDescription iotkit_secctl_ppc_vmstate = {
499
+ .name = "iotkit-secctl-ppc",
500
+ .version_id = 1,
501
+ .minimum_version_id = 1,
502
+ .fields = (VMStateField[]) {
503
+ VMSTATE_UINT32(ns, IoTKitSecCtlPPC),
504
+ VMSTATE_UINT32(sp, IoTKitSecCtlPPC),
505
+ VMSTATE_UINT32(nsp, IoTKitSecCtlPPC),
506
+ VMSTATE_END_OF_LIST()
507
+ }
508
+};
509
+
510
static const VMStateDescription iotkit_secctl_vmstate = {
511
.name = "iotkit-secctl",
512
.version_id = 1,
513
.minimum_version_id = 1,
514
.fields = (VMStateField[]) {
515
+ VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
516
+ VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
517
+ VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
518
+ VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
519
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
520
+ VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
521
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
522
+ VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1,
523
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
524
VMSTATE_END_OF_LIST()
525
}
526
};
527
--
333
--
528
2.16.2
334
2.20.1
529
335
530
336
diff view generated by jsdifflib
1
The or-irq.h header file is missing the customary guard against
1
We're about to move code from the template header into pxa2xx_lcd.c.
2
multiple inclusion, which means compilation fails if it gets
2
Before doing that, make coding style fixes so checkpatch doesn't
3
included twice. Fix the omission.
3
complain about the patch which moves the code. This commit fixes
4
missing braces in the SKIP_PIXEL() macro definition and in if()
5
statements.
4
6
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210211141515.8755-8-peter.maydell@linaro.org
8
Message-id: 20180220180325.29818-11-peter.maydell@linaro.org
9
---
10
---
10
include/hw/or-irq.h | 5 +++++
11
hw/display/pxa2xx_template.h | 47 +++++++++++++++++++++---------------
11
1 file changed, 5 insertions(+)
12
1 file changed, 28 insertions(+), 19 deletions(-)
12
13
13
diff --git a/include/hw/or-irq.h b/include/hw/or-irq.h
14
diff --git a/hw/display/pxa2xx_template.h b/hw/display/pxa2xx_template.h
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/or-irq.h
16
--- a/hw/display/pxa2xx_template.h
16
+++ b/include/hw/or-irq.h
17
+++ b/hw/display/pxa2xx_template.h
17
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
18
* THE SOFTWARE.
19
* Framebuffer format conversion routines.
19
*/
20
*/
20
21
21
+#ifndef HW_OR_IRQ_H
22
-# define SKIP_PIXEL(to)        to += deststep
22
+#define HW_OR_IRQ_H
23
+# define SKIP_PIXEL(to) do { to += deststep; } while (0)
23
+
24
# define COPY_PIXEL(to, from) \
24
#include "hw/irq.h"
25
do { \
25
#include "hw/sysbus.h"
26
*(uint32_t *) to = from; \
26
#include "qom/object.h"
27
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line16t(void *opaque,
27
@@ -XXX,XX +XXX,XX @@ struct OrIRQState {
28
data >>= 5;
28
bool levels[MAX_OR_LINES];
29
r = (data & 0x1f) << 3;
29
uint16_t num_lines;
30
data >>= 5;
30
};
31
- if (data & 1)
31
+
32
+ if (data & 1) {
32
+#endif
33
SKIP_PIXEL(dest);
34
- else
35
+ } else {
36
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
37
+ }
38
data >>= 1;
39
b = (data & 0x1f) << 3;
40
data >>= 5;
41
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line16t(void *opaque,
42
data >>= 5;
43
r = (data & 0x1f) << 3;
44
data >>= 5;
45
- if (data & 1)
46
+ if (data & 1) {
47
SKIP_PIXEL(dest);
48
- else
49
+ } else {
50
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
51
+ }
52
width -= 2;
53
src += 4;
54
}
55
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19(void *opaque,
56
data >>= 6;
57
r = (data & 0x3f) << 2;
58
data >>= 6;
59
- if (data & 1)
60
+ if (data & 1) {
61
SKIP_PIXEL(dest);
62
- else
63
+ } else {
64
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
65
+ }
66
width -= 1;
67
src += 4;
68
}
69
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19p(void *opaque,
70
data[0] >>= 6;
71
r = (data[0] & 0x3f) << 2;
72
data[0] >>= 6;
73
- if (data[0] & 1)
74
+ if (data[0] & 1) {
75
SKIP_PIXEL(dest);
76
- else
77
+ } else {
78
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
79
+ }
80
data[0] >>= 6;
81
b = (data[0] & 0x3f) << 2;
82
data[0] >>= 6;
83
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19p(void *opaque,
84
data[1] >>= 4;
85
r = (data[1] & 0x3f) << 2;
86
data[1] >>= 6;
87
- if (data[1] & 1)
88
+ if (data[1] & 1) {
89
SKIP_PIXEL(dest);
90
- else
91
+ } else {
92
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
93
+ }
94
data[1] >>= 6;
95
b = (data[1] & 0x3f) << 2;
96
data[1] >>= 6;
97
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19p(void *opaque,
98
data[1] >>= 6;
99
r = ((data[2] & 0x3) << 6) | (data[1] << 2);
100
data[2] >>= 2;
101
- if (data[2] & 1)
102
+ if (data[2] & 1) {
103
SKIP_PIXEL(dest);
104
- else
105
+ } else {
106
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
107
+ }
108
data[2] >>= 6;
109
b = (data[2] & 0x3f) << 2;
110
data[2] >>= 6;
111
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19p(void *opaque,
112
data[2] >>= 6;
113
r = data[2] << 2;
114
data[2] >>= 6;
115
- if (data[2] & 1)
116
+ if (data[2] & 1) {
117
SKIP_PIXEL(dest);
118
- else
119
+ } else {
120
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
121
+ }
122
width -= 4;
123
}
124
}
125
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line24t(void *opaque,
126
data >>= 8;
127
r = data & 0xff;
128
data >>= 8;
129
- if (data & 1)
130
+ if (data & 1) {
131
SKIP_PIXEL(dest);
132
- else
133
+ } else {
134
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
135
+ }
136
width -= 1;
137
src += 4;
138
}
139
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line25(void *opaque,
140
data >>= 8;
141
r = data & 0xff;
142
data >>= 8;
143
- if (data & 1)
144
+ if (data & 1) {
145
SKIP_PIXEL(dest);
146
- else
147
+ } else {
148
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
149
+ }
150
width -= 1;
151
src += 4;
152
}
33
--
153
--
34
2.16.2
154
2.20.1
35
155
36
156
diff view generated by jsdifflib
1
Instead of loading guest images to the system address space, use the
1
We're about to move code from the template header into pxa2xx_lcd.c.
2
CPU's address space. This is important if we're trying to load the
2
Before doing that, make coding style fixes so checkpatch doesn't
3
file to memory or via an alias memory region that is provided by an
3
complain about the patch which moves the code. This commit is
4
SoC object and thus not mapped into the system address space.
4
whitespace changes only:
5
* avoid hard-coded tabs
6
* fix ident on function prototypes
7
* no newline before open brace on array definitions
5
8
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210211141515.8755-9-peter.maydell@linaro.org
9
Message-id: 20180220180325.29818-4-peter.maydell@linaro.org
10
---
12
---
11
hw/arm/armv7m.c | 17 ++++++++++++++---
13
hw/display/pxa2xx_template.h | 66 +++++++++++++++++-------------------
12
1 file changed, 14 insertions(+), 3 deletions(-)
14
1 file changed, 32 insertions(+), 34 deletions(-)
13
15
14
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
16
diff --git a/hw/display/pxa2xx_template.h b/hw/display/pxa2xx_template.h
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/armv7m.c
18
--- a/hw/display/pxa2xx_template.h
17
+++ b/hw/arm/armv7m.c
19
+++ b/hw/display/pxa2xx_template.h
18
@@ -XXX,XX +XXX,XX @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
20
@@ -XXX,XX +XXX,XX @@
19
uint64_t entry;
21
} while (0)
20
uint64_t lowaddr;
22
21
int big_endian;
23
#ifdef HOST_WORDS_BIGENDIAN
22
+ AddressSpace *as;
24
-# define SWAP_WORDS    1
23
+ int asidx;
25
+# define SWAP_WORDS 1
24
+ CPUState *cs = CPU(cpu);
26
#endif
25
27
26
#ifdef TARGET_WORDS_BIGENDIAN
28
-#define FN_2(x)        FN(x + 1) FN(x)
27
big_endian = 1;
29
-#define FN_4(x)        FN_2(x + 2) FN_2(x)
28
@@ -XXX,XX +XXX,XX @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
30
+#define FN_2(x) FN(x + 1) FN(x)
29
exit(1);
31
+#define FN_4(x) FN_2(x + 2) FN_2(x)
30
}
32
31
33
-static void pxa2xx_draw_line2(void *opaque,
32
+ if (arm_feature(&cpu->env, ARM_FEATURE_EL3)) {
34
- uint8_t *dest, const uint8_t *src, int width, int deststep)
33
+ asidx = ARMASIdx_S;
35
+static void pxa2xx_draw_line2(void *opaque, uint8_t *dest, const uint8_t *src,
34
+ } else {
36
+ int width, int deststep)
35
+ asidx = ARMASIdx_NS;
37
{
36
+ }
38
uint32_t *palette = opaque;
37
+ as = cpu_get_address_space(cs, asidx);
39
uint32_t data;
38
+
40
while (width > 0) {
39
if (kernel_filename) {
41
data = *(uint32_t *) src;
40
- image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
42
-#define FN(x)        COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
41
- NULL, big_endian, EM_ARM, 1, 0);
43
+#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
42
+ image_size = load_elf_as(kernel_filename, NULL, NULL, &entry, &lowaddr,
44
#ifdef SWAP_WORDS
43
+ NULL, big_endian, EM_ARM, 1, 0, as);
45
FN_4(12)
44
if (image_size < 0) {
46
FN_4(8)
45
- image_size = load_image_targphys(kernel_filename, 0, mem_size);
47
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line2(void *opaque,
46
+ image_size = load_image_targphys_as(kernel_filename, 0,
48
}
47
+ mem_size, as);
49
}
48
lowaddr = 0;
50
49
}
51
-static void pxa2xx_draw_line4(void *opaque,
50
if (image_size < 0) {
52
- uint8_t *dest, const uint8_t *src, int width, int deststep)
53
+static void pxa2xx_draw_line4(void *opaque, uint8_t *dest, const uint8_t *src,
54
+ int width, int deststep)
55
{
56
uint32_t *palette = opaque;
57
uint32_t data;
58
while (width > 0) {
59
data = *(uint32_t *) src;
60
-#define FN(x)        COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
61
+#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
62
#ifdef SWAP_WORDS
63
FN_2(6)
64
FN_2(4)
65
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line4(void *opaque,
66
}
67
}
68
69
-static void pxa2xx_draw_line8(void *opaque,
70
- uint8_t *dest, const uint8_t *src, int width, int deststep)
71
+static void pxa2xx_draw_line8(void *opaque, uint8_t *dest, const uint8_t *src,
72
+ int width, int deststep)
73
{
74
uint32_t *palette = opaque;
75
uint32_t data;
76
while (width > 0) {
77
data = *(uint32_t *) src;
78
-#define FN(x)        COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
79
+#define FN(x) COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
80
#ifdef SWAP_WORDS
81
FN(24)
82
FN(16)
83
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line8(void *opaque,
84
}
85
}
86
87
-static void pxa2xx_draw_line16(void *opaque,
88
- uint8_t *dest, const uint8_t *src, int width, int deststep)
89
+static void pxa2xx_draw_line16(void *opaque, uint8_t *dest, const uint8_t *src,
90
+ int width, int deststep)
91
{
92
uint32_t data;
93
unsigned int r, g, b;
94
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line16(void *opaque,
95
}
96
}
97
98
-static void pxa2xx_draw_line16t(void *opaque,
99
- uint8_t *dest, const uint8_t *src, int width, int deststep)
100
+static void pxa2xx_draw_line16t(void *opaque, uint8_t *dest, const uint8_t *src,
101
+ int width, int deststep)
102
{
103
uint32_t data;
104
unsigned int r, g, b;
105
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line16t(void *opaque,
106
}
107
}
108
109
-static void pxa2xx_draw_line18(void *opaque,
110
- uint8_t *dest, const uint8_t *src, int width, int deststep)
111
+static void pxa2xx_draw_line18(void *opaque, uint8_t *dest, const uint8_t *src,
112
+ int width, int deststep)
113
{
114
uint32_t data;
115
unsigned int r, g, b;
116
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line18(void *opaque,
117
}
118
119
/* The wicked packed format */
120
-static void pxa2xx_draw_line18p(void *opaque,
121
- uint8_t *dest, const uint8_t *src, int width, int deststep)
122
+static void pxa2xx_draw_line18p(void *opaque, uint8_t *dest, const uint8_t *src,
123
+ int width, int deststep)
124
{
125
uint32_t data[3];
126
unsigned int r, g, b;
127
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line18p(void *opaque,
128
}
129
}
130
131
-static void pxa2xx_draw_line19(void *opaque,
132
- uint8_t *dest, const uint8_t *src, int width, int deststep)
133
+static void pxa2xx_draw_line19(void *opaque, uint8_t *dest, const uint8_t *src,
134
+ int width, int deststep)
135
{
136
uint32_t data;
137
unsigned int r, g, b;
138
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19(void *opaque,
139
}
140
141
/* The wicked packed format */
142
-static void pxa2xx_draw_line19p(void *opaque,
143
- uint8_t *dest, const uint8_t *src, int width, int deststep)
144
+static void pxa2xx_draw_line19p(void *opaque, uint8_t *dest, const uint8_t *src,
145
+ int width, int deststep)
146
{
147
uint32_t data[3];
148
unsigned int r, g, b;
149
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19p(void *opaque,
150
}
151
}
152
153
-static void pxa2xx_draw_line24(void *opaque,
154
- uint8_t *dest, const uint8_t *src, int width, int deststep)
155
+static void pxa2xx_draw_line24(void *opaque, uint8_t *dest, const uint8_t *src,
156
+ int width, int deststep)
157
{
158
uint32_t data;
159
unsigned int r, g, b;
160
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line24(void *opaque,
161
}
162
}
163
164
-static void pxa2xx_draw_line24t(void *opaque,
165
- uint8_t *dest, const uint8_t *src, int width, int deststep)
166
+static void pxa2xx_draw_line24t(void *opaque, uint8_t *dest, const uint8_t *src,
167
+ int width, int deststep)
168
{
169
uint32_t data;
170
unsigned int r, g, b;
171
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line24t(void *opaque,
172
}
173
}
174
175
-static void pxa2xx_draw_line25(void *opaque,
176
- uint8_t *dest, const uint8_t *src, int width, int deststep)
177
+static void pxa2xx_draw_line25(void *opaque, uint8_t *dest, const uint8_t *src,
178
+ int width, int deststep)
179
{
180
uint32_t data;
181
unsigned int r, g, b;
182
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line25(void *opaque,
183
}
184
185
/* Overlay planes disabled, no transparency */
186
-static drawfn pxa2xx_draw_fn_32[16] =
187
-{
188
+static drawfn pxa2xx_draw_fn_32[16] = {
189
[0 ... 0xf] = NULL,
190
[pxa_lcdc_2bpp] = pxa2xx_draw_line2,
191
[pxa_lcdc_4bpp] = pxa2xx_draw_line4,
192
@@ -XXX,XX +XXX,XX @@ static drawfn pxa2xx_draw_fn_32[16] =
193
};
194
195
/* Overlay planes enabled, transparency used */
196
-static drawfn pxa2xx_draw_fn_32t[16] =
197
-{
198
+static drawfn pxa2xx_draw_fn_32t[16] = {
199
[0 ... 0xf] = NULL,
200
[pxa_lcdc_4bpp] = pxa2xx_draw_line4,
201
[pxa_lcdc_8bpp] = pxa2xx_draw_line8,
51
--
202
--
52
2.16.2
203
2.20.1
53
204
54
205
diff view generated by jsdifflib
1
Model the Arm IoT Kit documented in
1
The template header is now included only once; just inline its contents
2
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
2
in hw/display/pxa2xx_lcd.c.
3
4
The Arm IoT Kit is a subsystem which includes a CPU and some devices,
5
and is intended be extended by adding extra devices to form a
6
complete system. It is used in the MPS2 board's AN505 image for the
7
Cortex-M33.
8
3
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
11
Message-id: 20180220180325.29818-19-peter.maydell@linaro.org
6
Message-id: 20210211141515.8755-10-peter.maydell@linaro.org
12
---
7
---
13
hw/arm/Makefile.objs | 1 +
8
hw/display/pxa2xx_template.h | 434 -----------------------------------
14
include/hw/arm/iotkit.h | 109 ++++++++
9
hw/display/pxa2xx_lcd.c | 427 +++++++++++++++++++++++++++++++++-
15
hw/arm/iotkit.c | 598 ++++++++++++++++++++++++++++++++++++++++
10
2 files changed, 425 insertions(+), 436 deletions(-)
16
default-configs/arm-softmmu.mak | 1 +
11
delete mode 100644 hw/display/pxa2xx_template.h
17
4 files changed, 709 insertions(+)
18
create mode 100644 include/hw/arm/iotkit.h
19
create mode 100644 hw/arm/iotkit.c
20
12
21
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
13
diff --git a/hw/display/pxa2xx_template.h b/hw/display/pxa2xx_template.h
14
deleted file mode 100644
15
index XXXXXXX..XXXXXXX
16
--- a/hw/display/pxa2xx_template.h
17
+++ /dev/null
18
@@ -XXX,XX +XXX,XX @@
19
-/*
20
- * Intel XScale PXA255/270 LCDC emulation.
21
- *
22
- * Copyright (c) 2006 Openedhand Ltd.
23
- * Written by Andrzej Zaborowski <balrog@zabor.org>
24
- *
25
- * This code is licensed under the GPLv2.
26
- *
27
- * Framebuffer format conversion routines.
28
- */
29
-
30
-# define SKIP_PIXEL(to) do { to += deststep; } while (0)
31
-# define COPY_PIXEL(to, from) \
32
- do { \
33
- *(uint32_t *) to = from; \
34
- SKIP_PIXEL(to); \
35
- } while (0)
36
-
37
-#ifdef HOST_WORDS_BIGENDIAN
38
-# define SWAP_WORDS 1
39
-#endif
40
-
41
-#define FN_2(x) FN(x + 1) FN(x)
42
-#define FN_4(x) FN_2(x + 2) FN_2(x)
43
-
44
-static void pxa2xx_draw_line2(void *opaque, uint8_t *dest, const uint8_t *src,
45
- int width, int deststep)
46
-{
47
- uint32_t *palette = opaque;
48
- uint32_t data;
49
- while (width > 0) {
50
- data = *(uint32_t *) src;
51
-#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
52
-#ifdef SWAP_WORDS
53
- FN_4(12)
54
- FN_4(8)
55
- FN_4(4)
56
- FN_4(0)
57
-#else
58
- FN_4(0)
59
- FN_4(4)
60
- FN_4(8)
61
- FN_4(12)
62
-#endif
63
-#undef FN
64
- width -= 16;
65
- src += 4;
66
- }
67
-}
68
-
69
-static void pxa2xx_draw_line4(void *opaque, uint8_t *dest, const uint8_t *src,
70
- int width, int deststep)
71
-{
72
- uint32_t *palette = opaque;
73
- uint32_t data;
74
- while (width > 0) {
75
- data = *(uint32_t *) src;
76
-#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
77
-#ifdef SWAP_WORDS
78
- FN_2(6)
79
- FN_2(4)
80
- FN_2(2)
81
- FN_2(0)
82
-#else
83
- FN_2(0)
84
- FN_2(2)
85
- FN_2(4)
86
- FN_2(6)
87
-#endif
88
-#undef FN
89
- width -= 8;
90
- src += 4;
91
- }
92
-}
93
-
94
-static void pxa2xx_draw_line8(void *opaque, uint8_t *dest, const uint8_t *src,
95
- int width, int deststep)
96
-{
97
- uint32_t *palette = opaque;
98
- uint32_t data;
99
- while (width > 0) {
100
- data = *(uint32_t *) src;
101
-#define FN(x) COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
102
-#ifdef SWAP_WORDS
103
- FN(24)
104
- FN(16)
105
- FN(8)
106
- FN(0)
107
-#else
108
- FN(0)
109
- FN(8)
110
- FN(16)
111
- FN(24)
112
-#endif
113
-#undef FN
114
- width -= 4;
115
- src += 4;
116
- }
117
-}
118
-
119
-static void pxa2xx_draw_line16(void *opaque, uint8_t *dest, const uint8_t *src,
120
- int width, int deststep)
121
-{
122
- uint32_t data;
123
- unsigned int r, g, b;
124
- while (width > 0) {
125
- data = *(uint32_t *) src;
126
-#ifdef SWAP_WORDS
127
- data = bswap32(data);
128
-#endif
129
- b = (data & 0x1f) << 3;
130
- data >>= 5;
131
- g = (data & 0x3f) << 2;
132
- data >>= 6;
133
- r = (data & 0x1f) << 3;
134
- data >>= 5;
135
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
136
- b = (data & 0x1f) << 3;
137
- data >>= 5;
138
- g = (data & 0x3f) << 2;
139
- data >>= 6;
140
- r = (data & 0x1f) << 3;
141
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
142
- width -= 2;
143
- src += 4;
144
- }
145
-}
146
-
147
-static void pxa2xx_draw_line16t(void *opaque, uint8_t *dest, const uint8_t *src,
148
- int width, int deststep)
149
-{
150
- uint32_t data;
151
- unsigned int r, g, b;
152
- while (width > 0) {
153
- data = *(uint32_t *) src;
154
-#ifdef SWAP_WORDS
155
- data = bswap32(data);
156
-#endif
157
- b = (data & 0x1f) << 3;
158
- data >>= 5;
159
- g = (data & 0x1f) << 3;
160
- data >>= 5;
161
- r = (data & 0x1f) << 3;
162
- data >>= 5;
163
- if (data & 1) {
164
- SKIP_PIXEL(dest);
165
- } else {
166
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
167
- }
168
- data >>= 1;
169
- b = (data & 0x1f) << 3;
170
- data >>= 5;
171
- g = (data & 0x1f) << 3;
172
- data >>= 5;
173
- r = (data & 0x1f) << 3;
174
- data >>= 5;
175
- if (data & 1) {
176
- SKIP_PIXEL(dest);
177
- } else {
178
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
179
- }
180
- width -= 2;
181
- src += 4;
182
- }
183
-}
184
-
185
-static void pxa2xx_draw_line18(void *opaque, uint8_t *dest, const uint8_t *src,
186
- int width, int deststep)
187
-{
188
- uint32_t data;
189
- unsigned int r, g, b;
190
- while (width > 0) {
191
- data = *(uint32_t *) src;
192
-#ifdef SWAP_WORDS
193
- data = bswap32(data);
194
-#endif
195
- b = (data & 0x3f) << 2;
196
- data >>= 6;
197
- g = (data & 0x3f) << 2;
198
- data >>= 6;
199
- r = (data & 0x3f) << 2;
200
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
201
- width -= 1;
202
- src += 4;
203
- }
204
-}
205
-
206
-/* The wicked packed format */
207
-static void pxa2xx_draw_line18p(void *opaque, uint8_t *dest, const uint8_t *src,
208
- int width, int deststep)
209
-{
210
- uint32_t data[3];
211
- unsigned int r, g, b;
212
- while (width > 0) {
213
- data[0] = *(uint32_t *) src;
214
- src += 4;
215
- data[1] = *(uint32_t *) src;
216
- src += 4;
217
- data[2] = *(uint32_t *) src;
218
- src += 4;
219
-#ifdef SWAP_WORDS
220
- data[0] = bswap32(data[0]);
221
- data[1] = bswap32(data[1]);
222
- data[2] = bswap32(data[2]);
223
-#endif
224
- b = (data[0] & 0x3f) << 2;
225
- data[0] >>= 6;
226
- g = (data[0] & 0x3f) << 2;
227
- data[0] >>= 6;
228
- r = (data[0] & 0x3f) << 2;
229
- data[0] >>= 12;
230
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
231
- b = (data[0] & 0x3f) << 2;
232
- data[0] >>= 6;
233
- g = ((data[1] & 0xf) << 4) | (data[0] << 2);
234
- data[1] >>= 4;
235
- r = (data[1] & 0x3f) << 2;
236
- data[1] >>= 12;
237
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
238
- b = (data[1] & 0x3f) << 2;
239
- data[1] >>= 6;
240
- g = (data[1] & 0x3f) << 2;
241
- data[1] >>= 6;
242
- r = ((data[2] & 0x3) << 6) | (data[1] << 2);
243
- data[2] >>= 8;
244
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
245
- b = (data[2] & 0x3f) << 2;
246
- data[2] >>= 6;
247
- g = (data[2] & 0x3f) << 2;
248
- data[2] >>= 6;
249
- r = data[2] << 2;
250
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
251
- width -= 4;
252
- }
253
-}
254
-
255
-static void pxa2xx_draw_line19(void *opaque, uint8_t *dest, const uint8_t *src,
256
- int width, int deststep)
257
-{
258
- uint32_t data;
259
- unsigned int r, g, b;
260
- while (width > 0) {
261
- data = *(uint32_t *) src;
262
-#ifdef SWAP_WORDS
263
- data = bswap32(data);
264
-#endif
265
- b = (data & 0x3f) << 2;
266
- data >>= 6;
267
- g = (data & 0x3f) << 2;
268
- data >>= 6;
269
- r = (data & 0x3f) << 2;
270
- data >>= 6;
271
- if (data & 1) {
272
- SKIP_PIXEL(dest);
273
- } else {
274
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
275
- }
276
- width -= 1;
277
- src += 4;
278
- }
279
-}
280
-
281
-/* The wicked packed format */
282
-static void pxa2xx_draw_line19p(void *opaque, uint8_t *dest, const uint8_t *src,
283
- int width, int deststep)
284
-{
285
- uint32_t data[3];
286
- unsigned int r, g, b;
287
- while (width > 0) {
288
- data[0] = *(uint32_t *) src;
289
- src += 4;
290
- data[1] = *(uint32_t *) src;
291
- src += 4;
292
- data[2] = *(uint32_t *) src;
293
- src += 4;
294
-# ifdef SWAP_WORDS
295
- data[0] = bswap32(data[0]);
296
- data[1] = bswap32(data[1]);
297
- data[2] = bswap32(data[2]);
298
-# endif
299
- b = (data[0] & 0x3f) << 2;
300
- data[0] >>= 6;
301
- g = (data[0] & 0x3f) << 2;
302
- data[0] >>= 6;
303
- r = (data[0] & 0x3f) << 2;
304
- data[0] >>= 6;
305
- if (data[0] & 1) {
306
- SKIP_PIXEL(dest);
307
- } else {
308
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
309
- }
310
- data[0] >>= 6;
311
- b = (data[0] & 0x3f) << 2;
312
- data[0] >>= 6;
313
- g = ((data[1] & 0xf) << 4) | (data[0] << 2);
314
- data[1] >>= 4;
315
- r = (data[1] & 0x3f) << 2;
316
- data[1] >>= 6;
317
- if (data[1] & 1) {
318
- SKIP_PIXEL(dest);
319
- } else {
320
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
321
- }
322
- data[1] >>= 6;
323
- b = (data[1] & 0x3f) << 2;
324
- data[1] >>= 6;
325
- g = (data[1] & 0x3f) << 2;
326
- data[1] >>= 6;
327
- r = ((data[2] & 0x3) << 6) | (data[1] << 2);
328
- data[2] >>= 2;
329
- if (data[2] & 1) {
330
- SKIP_PIXEL(dest);
331
- } else {
332
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
333
- }
334
- data[2] >>= 6;
335
- b = (data[2] & 0x3f) << 2;
336
- data[2] >>= 6;
337
- g = (data[2] & 0x3f) << 2;
338
- data[2] >>= 6;
339
- r = data[2] << 2;
340
- data[2] >>= 6;
341
- if (data[2] & 1) {
342
- SKIP_PIXEL(dest);
343
- } else {
344
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
345
- }
346
- width -= 4;
347
- }
348
-}
349
-
350
-static void pxa2xx_draw_line24(void *opaque, uint8_t *dest, const uint8_t *src,
351
- int width, int deststep)
352
-{
353
- uint32_t data;
354
- unsigned int r, g, b;
355
- while (width > 0) {
356
- data = *(uint32_t *) src;
357
-#ifdef SWAP_WORDS
358
- data = bswap32(data);
359
-#endif
360
- b = data & 0xff;
361
- data >>= 8;
362
- g = data & 0xff;
363
- data >>= 8;
364
- r = data & 0xff;
365
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
366
- width -= 1;
367
- src += 4;
368
- }
369
-}
370
-
371
-static void pxa2xx_draw_line24t(void *opaque, uint8_t *dest, const uint8_t *src,
372
- int width, int deststep)
373
-{
374
- uint32_t data;
375
- unsigned int r, g, b;
376
- while (width > 0) {
377
- data = *(uint32_t *) src;
378
-#ifdef SWAP_WORDS
379
- data = bswap32(data);
380
-#endif
381
- b = (data & 0x7f) << 1;
382
- data >>= 7;
383
- g = data & 0xff;
384
- data >>= 8;
385
- r = data & 0xff;
386
- data >>= 8;
387
- if (data & 1) {
388
- SKIP_PIXEL(dest);
389
- } else {
390
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
391
- }
392
- width -= 1;
393
- src += 4;
394
- }
395
-}
396
-
397
-static void pxa2xx_draw_line25(void *opaque, uint8_t *dest, const uint8_t *src,
398
- int width, int deststep)
399
-{
400
- uint32_t data;
401
- unsigned int r, g, b;
402
- while (width > 0) {
403
- data = *(uint32_t *) src;
404
-#ifdef SWAP_WORDS
405
- data = bswap32(data);
406
-#endif
407
- b = data & 0xff;
408
- data >>= 8;
409
- g = data & 0xff;
410
- data >>= 8;
411
- r = data & 0xff;
412
- data >>= 8;
413
- if (data & 1) {
414
- SKIP_PIXEL(dest);
415
- } else {
416
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
417
- }
418
- width -= 1;
419
- src += 4;
420
- }
421
-}
422
-
423
-/* Overlay planes disabled, no transparency */
424
-static drawfn pxa2xx_draw_fn_32[16] = {
425
- [0 ... 0xf] = NULL,
426
- [pxa_lcdc_2bpp] = pxa2xx_draw_line2,
427
- [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
428
- [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
429
- [pxa_lcdc_16bpp] = pxa2xx_draw_line16,
430
- [pxa_lcdc_18bpp] = pxa2xx_draw_line18,
431
- [pxa_lcdc_18pbpp] = pxa2xx_draw_line18p,
432
- [pxa_lcdc_24bpp] = pxa2xx_draw_line24,
433
-};
434
-
435
-/* Overlay planes enabled, transparency used */
436
-static drawfn pxa2xx_draw_fn_32t[16] = {
437
- [0 ... 0xf] = NULL,
438
- [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
439
- [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
440
- [pxa_lcdc_16bpp] = pxa2xx_draw_line16t,
441
- [pxa_lcdc_19bpp] = pxa2xx_draw_line19,
442
- [pxa_lcdc_19pbpp] = pxa2xx_draw_line19p,
443
- [pxa_lcdc_24bpp] = pxa2xx_draw_line24t,
444
- [pxa_lcdc_25bpp] = pxa2xx_draw_line25,
445
-};
446
-
447
-#undef COPY_PIXEL
448
-#undef SKIP_PIXEL
449
-
450
-#ifdef SWAP_WORDS
451
-# undef SWAP_WORDS
452
-#endif
453
diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c
22
index XXXXXXX..XXXXXXX 100644
454
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/Makefile.objs
455
--- a/hw/display/pxa2xx_lcd.c
24
+++ b/hw/arm/Makefile.objs
456
+++ b/hw/display/pxa2xx_lcd.c
25
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
457
@@ -XXX,XX +XXX,XX @@ typedef struct QEMU_PACKED {
26
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
458
/* Size of a pixel in the QEMU UI output surface, in bytes */
27
obj-$(CONFIG_MPS2) += mps2.o
459
#define DEST_PIXEL_WIDTH 4
28
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
460
29
+obj-$(CONFIG_IOTKIT) += iotkit.o
461
-#define BITS 32
30
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
462
-#include "pxa2xx_template.h"
31
new file mode 100644
463
+/* Line drawing code to handle the various possible guest pixel formats */
32
index XXXXXXX..XXXXXXX
464
+
33
--- /dev/null
465
+# define SKIP_PIXEL(to) do { to += deststep; } while (0)
34
+++ b/include/hw/arm/iotkit.h
466
+# define COPY_PIXEL(to, from) \
35
@@ -XXX,XX +XXX,XX @@
467
+ do { \
36
+/*
468
+ *(uint32_t *) to = from; \
37
+ * ARM IoT Kit
469
+ SKIP_PIXEL(to); \
38
+ *
470
+ } while (0)
39
+ * Copyright (c) 2018 Linaro Limited
471
+
40
+ * Written by Peter Maydell
472
+#ifdef HOST_WORDS_BIGENDIAN
41
+ *
473
+# define SWAP_WORDS 1
42
+ * This program is free software; you can redistribute it and/or modify
474
+#endif
43
+ * it under the terms of the GNU General Public License version 2 or
475
+
44
+ * (at your option) any later version.
476
+#define FN_2(x) FN(x + 1) FN(x)
45
+ */
477
+#define FN_4(x) FN_2(x + 2) FN_2(x)
46
+
478
+
47
+/* This is a model of the Arm IoT Kit which is documented in
479
+static void pxa2xx_draw_line2(void *opaque, uint8_t *dest, const uint8_t *src,
48
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
480
+ int width, int deststep)
49
+ * It contains:
481
+{
50
+ * a Cortex-M33
482
+ uint32_t *palette = opaque;
51
+ * the IDAU
483
+ uint32_t data;
52
+ * some timers and watchdogs
484
+ while (width > 0) {
53
+ * two peripheral protection controllers
485
+ data = *(uint32_t *) src;
54
+ * a memory protection controller
486
+#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
55
+ * a security controller
487
+#ifdef SWAP_WORDS
56
+ * a bus fabric which arranges that some parts of the address
488
+ FN_4(12)
57
+ * space are secure and non-secure aliases of each other
489
+ FN_4(8)
58
+ *
490
+ FN_4(4)
59
+ * QEMU interface:
491
+ FN_4(0)
60
+ * + QOM property "memory" is a MemoryRegion containing the devices provided
492
+#else
61
+ * by the board model.
493
+ FN_4(0)
62
+ * + QOM property "MAINCLK" is the frequency of the main system clock
494
+ FN_4(4)
63
+ * + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts
495
+ FN_4(8)
64
+ * + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts, which
496
+ FN_4(12)
65
+ * are wired to the NVIC lines 32 .. n+32
497
+#endif
66
+ * Controlling up to 4 AHB expansion PPBs which a system using the IoTKit
498
+#undef FN
67
+ * might provide:
499
+ width -= 16;
68
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15]
500
+ src += 4;
69
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_ap[0..15]
501
+ }
70
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_enable
502
+}
71
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_clear
503
+
72
+ * + named GPIO inputs apb_ppcexp{0,1,2,3}_irq_status
504
+static void pxa2xx_draw_line4(void *opaque, uint8_t *dest, const uint8_t *src,
73
+ * Controlling each of the 4 expansion AHB PPCs which a system using the IoTKit
505
+ int width, int deststep)
74
+ * might provide:
506
+{
75
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_nonsec[0..15]
507
+ uint32_t *palette = opaque;
76
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_ap[0..15]
508
+ uint32_t data;
77
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
509
+ while (width > 0) {
78
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
510
+ data = *(uint32_t *) src;
79
+ * + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
511
+#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
80
+ */
512
+#ifdef SWAP_WORDS
81
+
513
+ FN_2(6)
82
+#ifndef IOTKIT_H
514
+ FN_2(4)
83
+#define IOTKIT_H
515
+ FN_2(2)
84
+
516
+ FN_2(0)
85
+#include "hw/sysbus.h"
517
+#else
86
+#include "hw/arm/armv7m.h"
518
+ FN_2(0)
87
+#include "hw/misc/iotkit-secctl.h"
519
+ FN_2(2)
88
+#include "hw/misc/tz-ppc.h"
520
+ FN_2(4)
89
+#include "hw/timer/cmsdk-apb-timer.h"
521
+ FN_2(6)
90
+#include "hw/misc/unimp.h"
522
+#endif
91
+#include "hw/or-irq.h"
523
+#undef FN
92
+#include "hw/core/split-irq.h"
524
+ width -= 8;
93
+
525
+ src += 4;
94
+#define TYPE_IOTKIT "iotkit"
526
+ }
95
+#define IOTKIT(obj) OBJECT_CHECK(IoTKit, (obj), TYPE_IOTKIT)
527
+}
96
+
528
+
97
+/* We have an IRQ splitter and an OR gate input for each external PPC
529
+static void pxa2xx_draw_line8(void *opaque, uint8_t *dest, const uint8_t *src,
98
+ * and the 2 internal PPCs
530
+ int width, int deststep)
99
+ */
531
+{
100
+#define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
532
+ uint32_t *palette = opaque;
101
+#define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
533
+ uint32_t data;
102
+
534
+ while (width > 0) {
103
+typedef struct IoTKit {
535
+ data = *(uint32_t *) src;
104
+ /*< private >*/
536
+#define FN(x) COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
105
+ SysBusDevice parent_obj;
537
+#ifdef SWAP_WORDS
106
+
538
+ FN(24)
107
+ /*< public >*/
539
+ FN(16)
108
+ ARMv7MState armv7m;
540
+ FN(8)
109
+ IoTKitSecCtl secctl;
541
+ FN(0)
110
+ TZPPC apb_ppc0;
542
+#else
111
+ TZPPC apb_ppc1;
543
+ FN(0)
112
+ CMSDKAPBTIMER timer0;
544
+ FN(8)
113
+ CMSDKAPBTIMER timer1;
545
+ FN(16)
114
+ qemu_or_irq ppc_irq_orgate;
546
+ FN(24)
115
+ SplitIRQ sec_resp_splitter;
547
+#endif
116
+ SplitIRQ ppc_irq_splitter[NUM_PPCS];
548
+#undef FN
117
+
549
+ width -= 4;
118
+ UnimplementedDeviceState dualtimer;
550
+ src += 4;
119
+ UnimplementedDeviceState s32ktimer;
551
+ }
120
+
552
+}
121
+ MemoryRegion container;
553
+
122
+ MemoryRegion alias1;
554
+static void pxa2xx_draw_line16(void *opaque, uint8_t *dest, const uint8_t *src,
123
+ MemoryRegion alias2;
555
+ int width, int deststep)
124
+ MemoryRegion alias3;
556
+{
125
+ MemoryRegion sram0;
557
+ uint32_t data;
126
+
558
+ unsigned int r, g, b;
127
+ qemu_irq *exp_irqs;
559
+ while (width > 0) {
128
+ qemu_irq ppc0_irq;
560
+ data = *(uint32_t *) src;
129
+ qemu_irq ppc1_irq;
561
+#ifdef SWAP_WORDS
130
+ qemu_irq sec_resp_cfg;
562
+ data = bswap32(data);
131
+ qemu_irq sec_resp_cfg_in;
563
+#endif
132
+ qemu_irq nsc_cfg_in;
564
+ b = (data & 0x1f) << 3;
133
+
565
+ data >>= 5;
134
+ qemu_irq irq_status_in[NUM_EXTERNAL_PPCS];
566
+ g = (data & 0x3f) << 2;
135
+
567
+ data >>= 6;
136
+ uint32_t nsccfg;
568
+ r = (data & 0x1f) << 3;
137
+
569
+ data >>= 5;
138
+ /* Properties */
570
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
139
+ MemoryRegion *board_memory;
571
+ b = (data & 0x1f) << 3;
140
+ uint32_t exp_numirq;
572
+ data >>= 5;
141
+ uint32_t mainclk_frq;
573
+ g = (data & 0x3f) << 2;
142
+} IoTKit;
574
+ data >>= 6;
143
+
575
+ r = (data & 0x1f) << 3;
144
+#endif
576
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
145
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
577
+ width -= 2;
146
new file mode 100644
578
+ src += 4;
147
index XXXXXXX..XXXXXXX
579
+ }
148
--- /dev/null
580
+}
149
+++ b/hw/arm/iotkit.c
581
+
150
@@ -XXX,XX +XXX,XX @@
582
+static void pxa2xx_draw_line16t(void *opaque, uint8_t *dest, const uint8_t *src,
151
+/*
583
+ int width, int deststep)
152
+ * Arm IoT Kit
584
+{
153
+ *
585
+ uint32_t data;
154
+ * Copyright (c) 2018 Linaro Limited
586
+ unsigned int r, g, b;
155
+ * Written by Peter Maydell
587
+ while (width > 0) {
156
+ *
588
+ data = *(uint32_t *) src;
157
+ * This program is free software; you can redistribute it and/or modify
589
+#ifdef SWAP_WORDS
158
+ * it under the terms of the GNU General Public License version 2 or
590
+ data = bswap32(data);
159
+ * (at your option) any later version.
591
+#endif
160
+ */
592
+ b = (data & 0x1f) << 3;
161
+
593
+ data >>= 5;
162
+#include "qemu/osdep.h"
594
+ g = (data & 0x1f) << 3;
163
+#include "qemu/log.h"
595
+ data >>= 5;
164
+#include "qapi/error.h"
596
+ r = (data & 0x1f) << 3;
165
+#include "trace.h"
597
+ data >>= 5;
166
+#include "hw/sysbus.h"
598
+ if (data & 1) {
167
+#include "hw/registerfields.h"
599
+ SKIP_PIXEL(dest);
168
+#include "hw/arm/iotkit.h"
600
+ } else {
169
+#include "hw/misc/unimp.h"
601
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
170
+#include "hw/arm/arm.h"
171
+
172
+/* Create an alias region of @size bytes starting at @base
173
+ * which mirrors the memory starting at @orig.
174
+ */
175
+static void make_alias(IoTKit *s, MemoryRegion *mr, const char *name,
176
+ hwaddr base, hwaddr size, hwaddr orig)
177
+{
178
+ memory_region_init_alias(mr, NULL, name, &s->container, orig, size);
179
+ /* The alias is even lower priority than unimplemented_device regions */
180
+ memory_region_add_subregion_overlap(&s->container, base, mr, -1500);
181
+}
182
+
183
+static void init_sysbus_child(Object *parent, const char *childname,
184
+ void *child, size_t childsize,
185
+ const char *childtype)
186
+{
187
+ object_initialize(child, childsize, childtype);
188
+ object_property_add_child(parent, childname, OBJECT(child), &error_abort);
189
+ qdev_set_parent_bus(DEVICE(child), sysbus_get_default());
190
+}
191
+
192
+static void irq_status_forwarder(void *opaque, int n, int level)
193
+{
194
+ qemu_irq destirq = opaque;
195
+
196
+ qemu_set_irq(destirq, level);
197
+}
198
+
199
+static void nsccfg_handler(void *opaque, int n, int level)
200
+{
201
+ IoTKit *s = IOTKIT(opaque);
202
+
203
+ s->nsccfg = level;
204
+}
205
+
206
+static void iotkit_forward_ppc(IoTKit *s, const char *ppcname, int ppcnum)
207
+{
208
+ /* Each of the 4 AHB and 4 APB PPCs that might be present in a
209
+ * system using the IoTKit has a collection of control lines which
210
+ * are provided by the security controller and which we want to
211
+ * expose as control lines on the IoTKit device itself, so the
212
+ * code using the IoTKit can wire them up to the PPCs.
213
+ */
214
+ SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum];
215
+ DeviceState *iotkitdev = DEVICE(s);
216
+ DeviceState *dev_secctl = DEVICE(&s->secctl);
217
+ DeviceState *dev_splitter = DEVICE(splitter);
218
+ char *name;
219
+
220
+ name = g_strdup_printf("%s_nonsec", ppcname);
221
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
222
+ g_free(name);
223
+ name = g_strdup_printf("%s_ap", ppcname);
224
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
225
+ g_free(name);
226
+ name = g_strdup_printf("%s_irq_enable", ppcname);
227
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
228
+ g_free(name);
229
+ name = g_strdup_printf("%s_irq_clear", ppcname);
230
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
231
+ g_free(name);
232
+
233
+ /* irq_status is a little more tricky, because we need to
234
+ * split it so we can send it both to the security controller
235
+ * and to our OR gate for the NVIC interrupt line.
236
+ * Connect up the splitter's outputs, and create a GPIO input
237
+ * which will pass the line state to the input splitter.
238
+ */
239
+ name = g_strdup_printf("%s_irq_status", ppcname);
240
+ qdev_connect_gpio_out(dev_splitter, 0,
241
+ qdev_get_gpio_in_named(dev_secctl,
242
+ name, 0));
243
+ qdev_connect_gpio_out(dev_splitter, 1,
244
+ qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), ppcnum));
245
+ s->irq_status_in[ppcnum] = qdev_get_gpio_in(dev_splitter, 0);
246
+ qdev_init_gpio_in_named_with_opaque(iotkitdev, irq_status_forwarder,
247
+ s->irq_status_in[ppcnum], name, 1);
248
+ g_free(name);
249
+}
250
+
251
+static void iotkit_forward_sec_resp_cfg(IoTKit *s)
252
+{
253
+ /* Forward the 3rd output from the splitter device as a
254
+ * named GPIO output of the iotkit object.
255
+ */
256
+ DeviceState *dev = DEVICE(s);
257
+ DeviceState *dev_splitter = DEVICE(&s->sec_resp_splitter);
258
+
259
+ qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
260
+ s->sec_resp_cfg_in = qemu_allocate_irq(irq_status_forwarder,
261
+ s->sec_resp_cfg, 1);
262
+ qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
263
+}
264
+
265
+static void iotkit_init(Object *obj)
266
+{
267
+ IoTKit *s = IOTKIT(obj);
268
+ int i;
269
+
270
+ memory_region_init(&s->container, obj, "iotkit-container", UINT64_MAX);
271
+
272
+ init_sysbus_child(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
273
+ TYPE_ARMV7M);
274
+ qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type",
275
+ ARM_CPU_TYPE_NAME("cortex-m33"));
276
+
277
+ init_sysbus_child(obj, "secctl", &s->secctl, sizeof(s->secctl),
278
+ TYPE_IOTKIT_SECCTL);
279
+ init_sysbus_child(obj, "apb-ppc0", &s->apb_ppc0, sizeof(s->apb_ppc0),
280
+ TYPE_TZ_PPC);
281
+ init_sysbus_child(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
282
+ TYPE_TZ_PPC);
283
+ init_sysbus_child(obj, "timer0", &s->timer0, sizeof(s->timer0),
284
+ TYPE_CMSDK_APB_TIMER);
285
+ init_sysbus_child(obj, "timer1", &s->timer1, sizeof(s->timer1),
286
+ TYPE_CMSDK_APB_TIMER);
287
+ init_sysbus_child(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer),
288
+ TYPE_UNIMPLEMENTED_DEVICE);
289
+ object_initialize(&s->ppc_irq_orgate, sizeof(s->ppc_irq_orgate),
290
+ TYPE_OR_IRQ);
291
+ object_property_add_child(obj, "ppc-irq-orgate",
292
+ OBJECT(&s->ppc_irq_orgate), &error_abort);
293
+ object_initialize(&s->sec_resp_splitter, sizeof(s->sec_resp_splitter),
294
+ TYPE_SPLIT_IRQ);
295
+ object_property_add_child(obj, "sec-resp-splitter",
296
+ OBJECT(&s->sec_resp_splitter), &error_abort);
297
+ for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
298
+ char *name = g_strdup_printf("ppc-irq-splitter-%d", i);
299
+ SplitIRQ *splitter = &s->ppc_irq_splitter[i];
300
+
301
+ object_initialize(splitter, sizeof(*splitter), TYPE_SPLIT_IRQ);
302
+ object_property_add_child(obj, name, OBJECT(splitter), &error_abort);
303
+ }
304
+ init_sysbus_child(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32ktimer),
305
+ TYPE_UNIMPLEMENTED_DEVICE);
306
+}
307
+
308
+static void iotkit_exp_irq(void *opaque, int n, int level)
309
+{
310
+ IoTKit *s = IOTKIT(opaque);
311
+
312
+ qemu_set_irq(s->exp_irqs[n], level);
313
+}
314
+
315
+static void iotkit_realize(DeviceState *dev, Error **errp)
316
+{
317
+ IoTKit *s = IOTKIT(dev);
318
+ int i;
319
+ MemoryRegion *mr;
320
+ Error *err = NULL;
321
+ SysBusDevice *sbd_apb_ppc0;
322
+ SysBusDevice *sbd_secctl;
323
+ DeviceState *dev_apb_ppc0;
324
+ DeviceState *dev_apb_ppc1;
325
+ DeviceState *dev_secctl;
326
+ DeviceState *dev_splitter;
327
+
328
+ if (!s->board_memory) {
329
+ error_setg(errp, "memory property was not set");
330
+ return;
331
+ }
332
+
333
+ if (!s->mainclk_frq) {
334
+ error_setg(errp, "MAINCLK property was not set");
335
+ return;
336
+ }
337
+
338
+ /* Handling of which devices should be available only to secure
339
+ * code is usually done differently for M profile than for A profile.
340
+ * Instead of putting some devices only into the secure address space,
341
+ * devices exist in both address spaces but with hard-wired security
342
+ * permissions that will cause the CPU to fault for non-secure accesses.
343
+ *
344
+ * The IoTKit has an IDAU (Implementation Defined Access Unit),
345
+ * which specifies hard-wired security permissions for different
346
+ * areas of the physical address space. For the IoTKit IDAU, the
347
+ * top 4 bits of the physical address are the IDAU region ID, and
348
+ * if bit 28 (ie the lowest bit of the ID) is 0 then this is an NS
349
+ * region, otherwise it is an S region.
350
+ *
351
+ * The various devices and RAMs are generally all mapped twice,
352
+ * once into a region that the IDAU defines as secure and once
353
+ * into a non-secure region. They sit behind either a Memory
354
+ * Protection Controller (for RAM) or a Peripheral Protection
355
+ * Controller (for devices), which allow a more fine grained
356
+ * configuration of whether non-secure accesses are permitted.
357
+ *
358
+ * (The other place that guest software can configure security
359
+ * permissions is in the architected SAU (Security Attribution
360
+ * Unit), which is entirely inside the CPU. The IDAU can upgrade
361
+ * the security attributes for a region to more restrictive than
362
+ * the SAU specifies, but cannot downgrade them.)
363
+ *
364
+ * 0x10000000..0x1fffffff alias of 0x00000000..0x0fffffff
365
+ * 0x20000000..0x2007ffff 32KB FPGA block RAM
366
+ * 0x30000000..0x3fffffff alias of 0x20000000..0x2fffffff
367
+ * 0x40000000..0x4000ffff base peripheral region 1
368
+ * 0x40010000..0x4001ffff CPU peripherals (none for IoTKit)
369
+ * 0x40020000..0x4002ffff system control element peripherals
370
+ * 0x40080000..0x400fffff base peripheral region 2
371
+ * 0x50000000..0x5fffffff alias of 0x40000000..0x4fffffff
372
+ */
373
+
374
+ memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
375
+
376
+ qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", s->exp_numirq + 32);
377
+ /* In real hardware the initial Secure VTOR is set from the INITSVTOR0
378
+ * register in the IoT Kit System Control Register block, and the
379
+ * initial value of that is in turn specifiable by the FPGA that
380
+ * instantiates the IoT Kit. In QEMU we don't implement this wrinkle,
381
+ * and simply set the CPU's init-svtor to the IoT Kit default value.
382
+ */
383
+ qdev_prop_set_uint32(DEVICE(&s->armv7m), "init-svtor", 0x10000000);
384
+ object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container),
385
+ "memory", &err);
386
+ if (err) {
387
+ error_propagate(errp, err);
388
+ return;
389
+ }
390
+ object_property_set_link(OBJECT(&s->armv7m), OBJECT(s), "idau", &err);
391
+ if (err) {
392
+ error_propagate(errp, err);
393
+ return;
394
+ }
395
+ object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
396
+ if (err) {
397
+ error_propagate(errp, err);
398
+ return;
399
+ }
400
+
401
+ /* Connect our EXP_IRQ GPIOs to the NVIC's lines 32 and up. */
402
+ s->exp_irqs = g_new(qemu_irq, s->exp_numirq);
403
+ for (i = 0; i < s->exp_numirq; i++) {
404
+ s->exp_irqs[i] = qdev_get_gpio_in(DEVICE(&s->armv7m), i + 32);
405
+ }
406
+ qdev_init_gpio_in_named(dev, iotkit_exp_irq, "EXP_IRQ", s->exp_numirq);
407
+
408
+ /* Set up the big aliases first */
409
+ make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
410
+ make_alias(s, &s->alias2, "alias 2", 0x30000000, 0x10000000, 0x20000000);
411
+ /* The 0x50000000..0x5fffffff region is not a pure alias: it has
412
+ * a few extra devices that only appear there (generally the
413
+ * control interfaces for the protection controllers).
414
+ * We implement this by mapping those devices over the top of this
415
+ * alias MR at a higher priority.
416
+ */
417
+ make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000);
418
+
419
+ /* This RAM should be behind a Memory Protection Controller, but we
420
+ * don't implement that yet.
421
+ */
422
+ memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &err);
423
+ if (err) {
424
+ error_propagate(errp, err);
425
+ return;
426
+ }
427
+ memory_region_add_subregion(&s->container, 0x20000000, &s->sram0);
428
+
429
+ /* Security controller */
430
+ object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
431
+ if (err) {
432
+ error_propagate(errp, err);
433
+ return;
434
+ }
435
+ sbd_secctl = SYS_BUS_DEVICE(&s->secctl);
436
+ dev_secctl = DEVICE(&s->secctl);
437
+ sysbus_mmio_map(sbd_secctl, 0, 0x50080000);
438
+ sysbus_mmio_map(sbd_secctl, 1, 0x40080000);
439
+
440
+ s->nsc_cfg_in = qemu_allocate_irq(nsccfg_handler, s, 1);
441
+ qdev_connect_gpio_out_named(dev_secctl, "nsc_cfg", 0, s->nsc_cfg_in);
442
+
443
+ /* The sec_resp_cfg output from the security controller must be split into
444
+ * multiple lines, one for each of the PPCs within the IoTKit and one
445
+ * that will be an output from the IoTKit to the system.
446
+ */
447
+ object_property_set_int(OBJECT(&s->sec_resp_splitter), 3,
448
+ "num-lines", &err);
449
+ if (err) {
450
+ error_propagate(errp, err);
451
+ return;
452
+ }
453
+ object_property_set_bool(OBJECT(&s->sec_resp_splitter), true,
454
+ "realized", &err);
455
+ if (err) {
456
+ error_propagate(errp, err);
457
+ return;
458
+ }
459
+ dev_splitter = DEVICE(&s->sec_resp_splitter);
460
+ qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0,
461
+ qdev_get_gpio_in(dev_splitter, 0));
462
+
463
+ /* Devices behind APB PPC0:
464
+ * 0x40000000: timer0
465
+ * 0x40001000: timer1
466
+ * 0x40002000: dual timer
467
+ * We must configure and realize each downstream device and connect
468
+ * it to the appropriate PPC port; then we can realize the PPC and
469
+ * map its upstream ends to the right place in the container.
470
+ */
471
+ qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
472
+ object_property_set_bool(OBJECT(&s->timer0), true, "realized", &err);
473
+ if (err) {
474
+ error_propagate(errp, err);
475
+ return;
476
+ }
477
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
478
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
479
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0);
480
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[0]", &err);
481
+ if (err) {
482
+ error_propagate(errp, err);
483
+ return;
484
+ }
485
+
486
+ qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
487
+ object_property_set_bool(OBJECT(&s->timer1), true, "realized", &err);
488
+ if (err) {
489
+ error_propagate(errp, err);
490
+ return;
491
+ }
492
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
493
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
494
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
495
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[1]", &err);
496
+ if (err) {
497
+ error_propagate(errp, err);
498
+ return;
499
+ }
500
+
501
+ qdev_prop_set_string(DEVICE(&s->dualtimer), "name", "Dual timer");
502
+ qdev_prop_set_uint64(DEVICE(&s->dualtimer), "size", 0x1000);
503
+ object_property_set_bool(OBJECT(&s->dualtimer), true, "realized", &err);
504
+ if (err) {
505
+ error_propagate(errp, err);
506
+ return;
507
+ }
508
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
509
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err);
510
+ if (err) {
511
+ error_propagate(errp, err);
512
+ return;
513
+ }
514
+
515
+ object_property_set_bool(OBJECT(&s->apb_ppc0), true, "realized", &err);
516
+ if (err) {
517
+ error_propagate(errp, err);
518
+ return;
519
+ }
520
+
521
+ sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc0);
522
+ dev_apb_ppc0 = DEVICE(&s->apb_ppc0);
523
+
524
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0);
525
+ memory_region_add_subregion(&s->container, 0x40000000, mr);
526
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 1);
527
+ memory_region_add_subregion(&s->container, 0x40001000, mr);
528
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
529
+ memory_region_add_subregion(&s->container, 0x40002000, mr);
530
+ for (i = 0; i < IOTS_APB_PPC0_NUM_PORTS; i++) {
531
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_nonsec", i,
532
+ qdev_get_gpio_in_named(dev_apb_ppc0,
533
+ "cfg_nonsec", i));
534
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_ap", i,
535
+ qdev_get_gpio_in_named(dev_apb_ppc0,
536
+ "cfg_ap", i));
537
+ }
538
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_enable", 0,
539
+ qdev_get_gpio_in_named(dev_apb_ppc0,
540
+ "irq_enable", 0));
541
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_clear", 0,
542
+ qdev_get_gpio_in_named(dev_apb_ppc0,
543
+ "irq_clear", 0));
544
+ qdev_connect_gpio_out(dev_splitter, 0,
545
+ qdev_get_gpio_in_named(dev_apb_ppc0,
546
+ "cfg_sec_resp", 0));
547
+
548
+ /* All the PPC irq lines (from the 2 internal PPCs and the 8 external
549
+ * ones) are sent individually to the security controller, and also
550
+ * ORed together to give a single combined PPC interrupt to the NVIC.
551
+ */
552
+ object_property_set_int(OBJECT(&s->ppc_irq_orgate),
553
+ NUM_PPCS, "num-lines", &err);
554
+ if (err) {
555
+ error_propagate(errp, err);
556
+ return;
557
+ }
558
+ object_property_set_bool(OBJECT(&s->ppc_irq_orgate), true,
559
+ "realized", &err);
560
+ if (err) {
561
+ error_propagate(errp, err);
562
+ return;
563
+ }
564
+ qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
565
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 10));
566
+
567
+ /* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */
568
+
569
+ /* 0x40020000 .. 0x4002ffff : IoTKit system control peripheral region */
570
+ /* Devices behind APB PPC1:
571
+ * 0x4002f000: S32K timer
572
+ */
573
+ qdev_prop_set_string(DEVICE(&s->s32ktimer), "name", "S32KTIMER");
574
+ qdev_prop_set_uint64(DEVICE(&s->s32ktimer), "size", 0x1000);
575
+ object_property_set_bool(OBJECT(&s->s32ktimer), true, "realized", &err);
576
+ if (err) {
577
+ error_propagate(errp, err);
578
+ return;
579
+ }
580
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
581
+ object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err);
582
+ if (err) {
583
+ error_propagate(errp, err);
584
+ return;
585
+ }
586
+
587
+ object_property_set_bool(OBJECT(&s->apb_ppc1), true, "realized", &err);
588
+ if (err) {
589
+ error_propagate(errp, err);
590
+ return;
591
+ }
592
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc1), 0);
593
+ memory_region_add_subregion(&s->container, 0x4002f000, mr);
594
+
595
+ dev_apb_ppc1 = DEVICE(&s->apb_ppc1);
596
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
597
+ qdev_get_gpio_in_named(dev_apb_ppc1,
598
+ "cfg_nonsec", 0));
599
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_ap", 0,
600
+ qdev_get_gpio_in_named(dev_apb_ppc1,
601
+ "cfg_ap", 0));
602
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_enable", 0,
603
+ qdev_get_gpio_in_named(dev_apb_ppc1,
604
+ "irq_enable", 0));
605
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_clear", 0,
606
+ qdev_get_gpio_in_named(dev_apb_ppc1,
607
+ "irq_clear", 0));
608
+ qdev_connect_gpio_out(dev_splitter, 1,
609
+ qdev_get_gpio_in_named(dev_apb_ppc1,
610
+ "cfg_sec_resp", 0));
611
+
612
+ /* Using create_unimplemented_device() maps the stub into the
613
+ * system address space rather than into our container, but the
614
+ * overall effect to the guest is the same.
615
+ */
616
+ create_unimplemented_device("SYSINFO", 0x40020000, 0x1000);
617
+
618
+ create_unimplemented_device("SYSCONTROL", 0x50021000, 0x1000);
619
+ create_unimplemented_device("S32KWATCHDOG", 0x5002e000, 0x1000);
620
+
621
+ /* 0x40080000 .. 0x4008ffff : IoTKit second Base peripheral region */
622
+
623
+ create_unimplemented_device("NS watchdog", 0x40081000, 0x1000);
624
+ create_unimplemented_device("S watchdog", 0x50081000, 0x1000);
625
+
626
+ create_unimplemented_device("SRAM0 MPC", 0x50083000, 0x1000);
627
+
628
+ for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
629
+ Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
630
+
631
+ object_property_set_int(splitter, 2, "num-lines", &err);
632
+ if (err) {
633
+ error_propagate(errp, err);
634
+ return;
635
+ }
602
+ }
636
+ object_property_set_bool(splitter, true, "realized", &err);
603
+ data >>= 1;
637
+ if (err) {
604
+ b = (data & 0x1f) << 3;
638
+ error_propagate(errp, err);
605
+ data >>= 5;
639
+ return;
606
+ g = (data & 0x1f) << 3;
607
+ data >>= 5;
608
+ r = (data & 0x1f) << 3;
609
+ data >>= 5;
610
+ if (data & 1) {
611
+ SKIP_PIXEL(dest);
612
+ } else {
613
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
640
+ }
614
+ }
641
+ }
615
+ width -= 2;
642
+
616
+ src += 4;
643
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
617
+ }
644
+ char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
618
+}
645
+
619
+
646
+ iotkit_forward_ppc(s, ppcname, i);
620
+static void pxa2xx_draw_line18(void *opaque, uint8_t *dest, const uint8_t *src,
647
+ g_free(ppcname);
621
+ int width, int deststep)
648
+ }
622
+{
649
+
623
+ uint32_t data;
650
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
624
+ unsigned int r, g, b;
651
+ char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
625
+ while (width > 0) {
652
+
626
+ data = *(uint32_t *) src;
653
+ iotkit_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
627
+#ifdef SWAP_WORDS
654
+ g_free(ppcname);
628
+ data = bswap32(data);
655
+ }
629
+#endif
656
+
630
+ b = (data & 0x3f) << 2;
657
+ for (i = NUM_EXTERNAL_PPCS; i < NUM_PPCS; i++) {
631
+ data >>= 6;
658
+ /* Wire up IRQ splitter for internal PPCs */
632
+ g = (data & 0x3f) << 2;
659
+ DeviceState *devs = DEVICE(&s->ppc_irq_splitter[i]);
633
+ data >>= 6;
660
+ char *gpioname = g_strdup_printf("apb_ppc%d_irq_status",
634
+ r = (data & 0x3f) << 2;
661
+ i - NUM_EXTERNAL_PPCS);
635
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
662
+ TZPPC *ppc = (i == NUM_EXTERNAL_PPCS) ? &s->apb_ppc0 : &s->apb_ppc1;
636
+ width -= 1;
663
+
637
+ src += 4;
664
+ qdev_connect_gpio_out(devs, 0,
638
+ }
665
+ qdev_get_gpio_in_named(dev_secctl, gpioname, 0));
639
+}
666
+ qdev_connect_gpio_out(devs, 1,
640
+
667
+ qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), i));
641
+/* The wicked packed format */
668
+ qdev_connect_gpio_out_named(DEVICE(ppc), "irq", 0,
642
+static void pxa2xx_draw_line18p(void *opaque, uint8_t *dest, const uint8_t *src,
669
+ qdev_get_gpio_in(devs, 0));
643
+ int width, int deststep)
670
+ }
644
+{
671
+
645
+ uint32_t data[3];
672
+ iotkit_forward_sec_resp_cfg(s);
646
+ unsigned int r, g, b;
673
+
647
+ while (width > 0) {
674
+ system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
648
+ data[0] = *(uint32_t *) src;
675
+}
649
+ src += 4;
676
+
650
+ data[1] = *(uint32_t *) src;
677
+static void iotkit_idau_check(IDAUInterface *ii, uint32_t address,
651
+ src += 4;
678
+ int *iregion, bool *exempt, bool *ns, bool *nsc)
652
+ data[2] = *(uint32_t *) src;
679
+{
653
+ src += 4;
680
+ /* For IoTKit systems the IDAU responses are simple logical functions
654
+#ifdef SWAP_WORDS
681
+ * of the address bits. The NSC attribute is guest-adjustable via the
655
+ data[0] = bswap32(data[0]);
682
+ * NSCCFG register in the security controller.
656
+ data[1] = bswap32(data[1]);
683
+ */
657
+ data[2] = bswap32(data[2]);
684
+ IoTKit *s = IOTKIT(ii);
658
+#endif
685
+ int region = extract32(address, 28, 4);
659
+ b = (data[0] & 0x3f) << 2;
686
+
660
+ data[0] >>= 6;
687
+ *ns = !(region & 1);
661
+ g = (data[0] & 0x3f) << 2;
688
+ *nsc = (region == 1 && (s->nsccfg & 1)) || (region == 3 && (s->nsccfg & 2));
662
+ data[0] >>= 6;
689
+ /* 0xe0000000..0xe00fffff and 0xf0000000..0xf00fffff are exempt */
663
+ r = (data[0] & 0x3f) << 2;
690
+ *exempt = (address & 0xeff00000) == 0xe0000000;
664
+ data[0] >>= 12;
691
+ *iregion = region;
665
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
692
+}
666
+ b = (data[0] & 0x3f) << 2;
693
+
667
+ data[0] >>= 6;
694
+static const VMStateDescription iotkit_vmstate = {
668
+ g = ((data[1] & 0xf) << 4) | (data[0] << 2);
695
+ .name = "iotkit",
669
+ data[1] >>= 4;
696
+ .version_id = 1,
670
+ r = (data[1] & 0x3f) << 2;
697
+ .minimum_version_id = 1,
671
+ data[1] >>= 12;
698
+ .fields = (VMStateField[]) {
672
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
699
+ VMSTATE_UINT32(nsccfg, IoTKit),
673
+ b = (data[1] & 0x3f) << 2;
700
+ VMSTATE_END_OF_LIST()
674
+ data[1] >>= 6;
701
+ }
675
+ g = (data[1] & 0x3f) << 2;
676
+ data[1] >>= 6;
677
+ r = ((data[2] & 0x3) << 6) | (data[1] << 2);
678
+ data[2] >>= 8;
679
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
680
+ b = (data[2] & 0x3f) << 2;
681
+ data[2] >>= 6;
682
+ g = (data[2] & 0x3f) << 2;
683
+ data[2] >>= 6;
684
+ r = data[2] << 2;
685
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
686
+ width -= 4;
687
+ }
688
+}
689
+
690
+static void pxa2xx_draw_line19(void *opaque, uint8_t *dest, const uint8_t *src,
691
+ int width, int deststep)
692
+{
693
+ uint32_t data;
694
+ unsigned int r, g, b;
695
+ while (width > 0) {
696
+ data = *(uint32_t *) src;
697
+#ifdef SWAP_WORDS
698
+ data = bswap32(data);
699
+#endif
700
+ b = (data & 0x3f) << 2;
701
+ data >>= 6;
702
+ g = (data & 0x3f) << 2;
703
+ data >>= 6;
704
+ r = (data & 0x3f) << 2;
705
+ data >>= 6;
706
+ if (data & 1) {
707
+ SKIP_PIXEL(dest);
708
+ } else {
709
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
710
+ }
711
+ width -= 1;
712
+ src += 4;
713
+ }
714
+}
715
+
716
+/* The wicked packed format */
717
+static void pxa2xx_draw_line19p(void *opaque, uint8_t *dest, const uint8_t *src,
718
+ int width, int deststep)
719
+{
720
+ uint32_t data[3];
721
+ unsigned int r, g, b;
722
+ while (width > 0) {
723
+ data[0] = *(uint32_t *) src;
724
+ src += 4;
725
+ data[1] = *(uint32_t *) src;
726
+ src += 4;
727
+ data[2] = *(uint32_t *) src;
728
+ src += 4;
729
+# ifdef SWAP_WORDS
730
+ data[0] = bswap32(data[0]);
731
+ data[1] = bswap32(data[1]);
732
+ data[2] = bswap32(data[2]);
733
+# endif
734
+ b = (data[0] & 0x3f) << 2;
735
+ data[0] >>= 6;
736
+ g = (data[0] & 0x3f) << 2;
737
+ data[0] >>= 6;
738
+ r = (data[0] & 0x3f) << 2;
739
+ data[0] >>= 6;
740
+ if (data[0] & 1) {
741
+ SKIP_PIXEL(dest);
742
+ } else {
743
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
744
+ }
745
+ data[0] >>= 6;
746
+ b = (data[0] & 0x3f) << 2;
747
+ data[0] >>= 6;
748
+ g = ((data[1] & 0xf) << 4) | (data[0] << 2);
749
+ data[1] >>= 4;
750
+ r = (data[1] & 0x3f) << 2;
751
+ data[1] >>= 6;
752
+ if (data[1] & 1) {
753
+ SKIP_PIXEL(dest);
754
+ } else {
755
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
756
+ }
757
+ data[1] >>= 6;
758
+ b = (data[1] & 0x3f) << 2;
759
+ data[1] >>= 6;
760
+ g = (data[1] & 0x3f) << 2;
761
+ data[1] >>= 6;
762
+ r = ((data[2] & 0x3) << 6) | (data[1] << 2);
763
+ data[2] >>= 2;
764
+ if (data[2] & 1) {
765
+ SKIP_PIXEL(dest);
766
+ } else {
767
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
768
+ }
769
+ data[2] >>= 6;
770
+ b = (data[2] & 0x3f) << 2;
771
+ data[2] >>= 6;
772
+ g = (data[2] & 0x3f) << 2;
773
+ data[2] >>= 6;
774
+ r = data[2] << 2;
775
+ data[2] >>= 6;
776
+ if (data[2] & 1) {
777
+ SKIP_PIXEL(dest);
778
+ } else {
779
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
780
+ }
781
+ width -= 4;
782
+ }
783
+}
784
+
785
+static void pxa2xx_draw_line24(void *opaque, uint8_t *dest, const uint8_t *src,
786
+ int width, int deststep)
787
+{
788
+ uint32_t data;
789
+ unsigned int r, g, b;
790
+ while (width > 0) {
791
+ data = *(uint32_t *) src;
792
+#ifdef SWAP_WORDS
793
+ data = bswap32(data);
794
+#endif
795
+ b = data & 0xff;
796
+ data >>= 8;
797
+ g = data & 0xff;
798
+ data >>= 8;
799
+ r = data & 0xff;
800
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
801
+ width -= 1;
802
+ src += 4;
803
+ }
804
+}
805
+
806
+static void pxa2xx_draw_line24t(void *opaque, uint8_t *dest, const uint8_t *src,
807
+ int width, int deststep)
808
+{
809
+ uint32_t data;
810
+ unsigned int r, g, b;
811
+ while (width > 0) {
812
+ data = *(uint32_t *) src;
813
+#ifdef SWAP_WORDS
814
+ data = bswap32(data);
815
+#endif
816
+ b = (data & 0x7f) << 1;
817
+ data >>= 7;
818
+ g = data & 0xff;
819
+ data >>= 8;
820
+ r = data & 0xff;
821
+ data >>= 8;
822
+ if (data & 1) {
823
+ SKIP_PIXEL(dest);
824
+ } else {
825
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
826
+ }
827
+ width -= 1;
828
+ src += 4;
829
+ }
830
+}
831
+
832
+static void pxa2xx_draw_line25(void *opaque, uint8_t *dest, const uint8_t *src,
833
+ int width, int deststep)
834
+{
835
+ uint32_t data;
836
+ unsigned int r, g, b;
837
+ while (width > 0) {
838
+ data = *(uint32_t *) src;
839
+#ifdef SWAP_WORDS
840
+ data = bswap32(data);
841
+#endif
842
+ b = data & 0xff;
843
+ data >>= 8;
844
+ g = data & 0xff;
845
+ data >>= 8;
846
+ r = data & 0xff;
847
+ data >>= 8;
848
+ if (data & 1) {
849
+ SKIP_PIXEL(dest);
850
+ } else {
851
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
852
+ }
853
+ width -= 1;
854
+ src += 4;
855
+ }
856
+}
857
+
858
+/* Overlay planes disabled, no transparency */
859
+static drawfn pxa2xx_draw_fn_32[16] = {
860
+ [0 ... 0xf] = NULL,
861
+ [pxa_lcdc_2bpp] = pxa2xx_draw_line2,
862
+ [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
863
+ [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
864
+ [pxa_lcdc_16bpp] = pxa2xx_draw_line16,
865
+ [pxa_lcdc_18bpp] = pxa2xx_draw_line18,
866
+ [pxa_lcdc_18pbpp] = pxa2xx_draw_line18p,
867
+ [pxa_lcdc_24bpp] = pxa2xx_draw_line24,
702
+};
868
+};
703
+
869
+
704
+static Property iotkit_properties[] = {
870
+/* Overlay planes enabled, transparency used */
705
+ DEFINE_PROP_LINK("memory", IoTKit, board_memory, TYPE_MEMORY_REGION,
871
+static drawfn pxa2xx_draw_fn_32t[16] = {
706
+ MemoryRegion *),
872
+ [0 ... 0xf] = NULL,
707
+ DEFINE_PROP_UINT32("EXP_NUMIRQ", IoTKit, exp_numirq, 64),
873
+ [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
708
+ DEFINE_PROP_UINT32("MAINCLK", IoTKit, mainclk_frq, 0),
874
+ [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
709
+ DEFINE_PROP_END_OF_LIST()
875
+ [pxa_lcdc_16bpp] = pxa2xx_draw_line16t,
876
+ [pxa_lcdc_19bpp] = pxa2xx_draw_line19,
877
+ [pxa_lcdc_19pbpp] = pxa2xx_draw_line19p,
878
+ [pxa_lcdc_24bpp] = pxa2xx_draw_line24t,
879
+ [pxa_lcdc_25bpp] = pxa2xx_draw_line25,
710
+};
880
+};
711
+
881
+
712
+static void iotkit_reset(DeviceState *dev)
882
+#undef COPY_PIXEL
713
+{
883
+#undef SKIP_PIXEL
714
+ IoTKit *s = IOTKIT(dev);
884
+
715
+
885
+#ifdef SWAP_WORDS
716
+ s->nsccfg = 0;
886
+# undef SWAP_WORDS
717
+}
887
+#endif
718
+
888
719
+static void iotkit_class_init(ObjectClass *klass, void *data)
889
/* Route internal interrupt lines to the global IC */
720
+{
890
static void pxa2xx_lcdc_int_update(PXA2xxLCDState *s)
721
+ DeviceClass *dc = DEVICE_CLASS(klass);
722
+ IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
723
+
724
+ dc->realize = iotkit_realize;
725
+ dc->vmsd = &iotkit_vmstate;
726
+ dc->props = iotkit_properties;
727
+ dc->reset = iotkit_reset;
728
+ iic->check = iotkit_idau_check;
729
+}
730
+
731
+static const TypeInfo iotkit_info = {
732
+ .name = TYPE_IOTKIT,
733
+ .parent = TYPE_SYS_BUS_DEVICE,
734
+ .instance_size = sizeof(IoTKit),
735
+ .instance_init = iotkit_init,
736
+ .class_init = iotkit_class_init,
737
+ .interfaces = (InterfaceInfo[]) {
738
+ { TYPE_IDAU_INTERFACE },
739
+ { }
740
+ }
741
+};
742
+
743
+static void iotkit_register_types(void)
744
+{
745
+ type_register_static(&iotkit_info);
746
+}
747
+
748
+type_init(iotkit_register_types);
749
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
750
index XXXXXXX..XXXXXXX 100644
751
--- a/default-configs/arm-softmmu.mak
752
+++ b/default-configs/arm-softmmu.mak
753
@@ -XXX,XX +XXX,XX @@ CONFIG_MPS2_FPGAIO=y
754
CONFIG_MPS2_SCC=y
755
756
CONFIG_TZ_PPC=y
757
+CONFIG_IOTKIT=y
758
CONFIG_IOTKIT_SECCTL=y
759
760
CONFIG_VERSATILE_PCI=y
761
--
891
--
762
2.16.2
892
2.20.1
763
893
764
894
diff view generated by jsdifflib