1
First pullreq for 6.0: mostly my v8.1M work, plus some other
1
Last pullreq before 6.0 softfreeze: a few minor feature patches,
2
bits and pieces. (I still have a lot of stuff in my to-review
2
some bugfixes, some cleanups.
3
folder, which I may or may not get to before the Christmas break...)
4
3
5
thanks
6
-- PMM
4
-- PMM
7
5
8
The following changes since commit 5e7b204dbfae9a562fc73684986f936b97f63877:
6
The following changes since commit 6f34661b6c97a37a5efc27d31c037ddeda4547e2:
9
7
10
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2020-12-09 20:08:54 +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)
11
9
12
are available in the Git repository at:
10
are available in the Git repository at:
13
11
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201210
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210312-1
15
13
16
for you to fetch changes up to 71f916be1c7e9ede0e37d9cabc781b5a9e8638ff:
14
for you to fetch changes up to 41f09f2e9f09e4dd386d84174a6dcb5136af17ca:
17
15
18
hw/arm/armv7m: Correct typo in QOM object name (2020-12-10 11:44:56 +0000)
16
hw/display/pxa2xx: Inline template header (2021-03-12 13:26:08 +0000)
19
17
20
----------------------------------------------------------------
18
----------------------------------------------------------------
21
target-arm queue:
19
target-arm queue:
22
* hw/arm/smmuv3: Fix up L1STD_SPAN decoding
20
* versal: Support XRAMs and XRAM controller
23
* xlnx-zynqmp: Support Xilinx ZynqMP CAN controllers
21
* smmu: Various minor bug fixes
24
* sbsa-ref: allow to use Cortex-A53/57/72 cpus
22
* SVE emulation: fix bugs handling odd vector lengths
25
* Various minor code cleanups
23
* allwinner-sun8i-emac: traverse transmit queue using TX_CUR_DESC register value
26
* hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
24
* tests/acceptance: fix orangepi-pc acceptance tests
27
* Implement more pieces of ARMv8.1M support
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
28
29
29
----------------------------------------------------------------
30
----------------------------------------------------------------
30
Alex Chen (4):
31
Andrew Jones (2):
31
i.MX25: Fix bad printf format specifiers
32
accel: kvm: Fix kvm_type invocation
32
i.MX31: Fix bad printf format specifiers
33
hw/arm/virt: KVM: The IPA lower bound is 32
33
i.MX6: Fix bad printf format specifiers
34
i.MX6ul: Fix bad printf format specifiers
35
34
36
Havard Skinnemoen (1):
35
Edgar E. Iglesias (2):
37
tests/qtest/npcm7xx_rng-test: dump random data on failure
36
hw/misc: versal: Add a model of the XRAM controller
37
hw/arm: versal: Add support for the XRAMs
38
38
39
Kunkun Jiang (1):
39
Eric Auger (7):
40
hw/arm/smmuv3: Fix up L1STD_SPAN decoding
40
intel_iommu: Fix mask may be uninitialized in vtd_context_device_invalidate
41
dma: Introduce dma_aligned_pow2_mask()
42
virtio-iommu: Handle non power of 2 range invalidations
43
hw/arm/smmu-common: Fix smmu_iotlb_inv_iova when asid is not set
44
hw/arm/smmuv3: Enforce invalidation on a power of two range
45
hw/arm/smmuv3: Fix SMMU_CMD_CFGI_STE_RANGE handling
46
hw/arm/smmuv3: Uniformize sid traces
41
47
42
Marcin Juszkiewicz (1):
48
Hao Wu (5):
43
sbsa-ref: allow to use Cortex-A53/57/72 cpus
49
hw/misc: Add GPIOs for duty in NPCM7xx PWM
50
hw/misc: Add NPCM7XX MFT Module
51
hw/arm: Add MFT device to NPCM7xx Soc
52
hw/arm: Connect PWM fans in NPCM7XX boards
53
tests/qtest: Test PWM fan RPM using MFT in PWM test
44
54
45
Peter Maydell (25):
55
Niek Linnenbank (5):
46
hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
56
hw/net/allwinner-sun8i-emac: traverse transmit queue using TX_CUR_DESC register value
47
target/arm: Implement v8.1M PXN extension
57
tests/acceptance/boot_linux_console: remove Armbian 19.11.3 bionic test for orangepi-pc machine
48
target/arm: Don't clobber ID_PFR1.Security on M-profile cores
58
tests/acceptance/boot_linux_console: change URL for test_arm_orangepi_bionic_20_08
49
target/arm: Implement VSCCLRM insn
59
tests/acceptance: update sunxi kernel from armbian to 5.10.16
50
target/arm: Implement CLRM instruction
60
tests/acceptance: drop ARMBIAN_ARTIFACTS_CACHED condition for orangepi-pc, cubieboard tests
51
target/arm: Enforce M-profile VMRS/VMSR register restrictions
52
target/arm: Refactor M-profile VMSR/VMRS handling
53
target/arm: Move general-use constant expanders up in translate.c
54
target/arm: Implement VLDR/VSTR system register
55
target/arm: Implement M-profile FPSCR_nzcvqc
56
target/arm: Use new FPCR_NZCV_MASK constant
57
target/arm: Factor out preserve-fp-state from full_vfp_access_check()
58
target/arm: Implement FPCXT_S fp system register
59
hw/intc/armv7m_nvic: Update FPDSCR masking for v8.1M
60
target/arm: For v8.1M, always clear R0-R3, R12, APSR, EPSR on exception entry
61
target/arm: In v8.1M, don't set HFSR.FORCED on vector table fetch failures
62
target/arm: Implement v8.1M REVIDR register
63
target/arm: Implement new v8.1M NOCP check for exception return
64
target/arm: Implement new v8.1M VLLDM and VLSTM encodings
65
hw/intc/armv7m_nvic: Support v8.1M CCR.TRD bit
66
target/arm: Implement CCR_S.TRD behaviour for SG insns
67
hw/intc/armv7m_nvic: Fix "return from inactive handler" check
68
target/arm: Implement M-profile "minimal RAS implementation"
69
hw/intc/armv7m_nvic: Implement read/write for RAS register block
70
hw/arm/armv7m: Correct typo in QOM object name
71
61
72
Vikram Garhwal (4):
62
Peter Maydell (9):
73
hw/net/can: Introduce Xilinx ZynqMP CAN controller
63
hw/display/pl110: Remove dead code for non-32-bpp surfaces
74
xlnx-zynqmp: Connect Xilinx ZynqMP CAN controllers
64
hw/display/pl110: Pull included-once parts of template header into pl110.c
75
tests/qtest: Introduce tests for Xilinx ZynqMP CAN controller
65
hw/display/pl110: Remove use of BITS from pl110_template.h
76
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller
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
77
72
78
meson.build | 1 +
73
Philippe Mathieu-Daudé (1):
79
hw/arm/smmuv3-internal.h | 2 +-
74
hw/timer/sse-timer: Propagate eventual error in sse_timer_realize()
80
hw/net/can/trace.h | 1 +
81
include/hw/arm/xlnx-zynqmp.h | 8 +
82
include/hw/intc/armv7m_nvic.h | 2 +
83
include/hw/net/xlnx-zynqmp-can.h | 78 +++
84
target/arm/cpu.h | 46 ++
85
target/arm/m-nocp.decode | 10 +-
86
target/arm/t32.decode | 10 +-
87
target/arm/vfp.decode | 14 +
88
hw/arm/armv7m.c | 4 +-
89
hw/arm/sbsa-ref.c | 23 +-
90
hw/arm/xlnx-zcu102.c | 20 +
91
hw/arm/xlnx-zynqmp.c | 34 ++
92
hw/intc/armv7m_nvic.c | 246 ++++++--
93
hw/misc/imx25_ccm.c | 12 +-
94
hw/misc/imx31_ccm.c | 14 +-
95
hw/misc/imx6_ccm.c | 20 +-
96
hw/misc/imx6_src.c | 2 +-
97
hw/misc/imx6ul_ccm.c | 4 +-
98
hw/misc/imx_ccm.c | 4 +-
99
hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++++++++++
100
target/arm/cpu.c | 5 +-
101
target/arm/helper.c | 7 +-
102
target/arm/m_helper.c | 130 ++++-
103
target/arm/translate.c | 105 +++-
104
tests/qtest/npcm7xx_rng-test.c | 12 +
105
tests/qtest/xlnx-can-test.c | 360 ++++++++++++
106
MAINTAINERS | 8 +
107
hw/Kconfig | 1 +
108
hw/net/can/meson.build | 1 +
109
hw/net/can/trace-events | 9 +
110
target/arm/translate-vfp.c.inc | 511 ++++++++++++++++-
111
tests/qtest/meson.build | 1 +
112
34 files changed, 2713 insertions(+), 153 deletions(-)
113
create mode 100644 hw/net/can/trace.h
114
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
115
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
116
create mode 100644 tests/qtest/xlnx-can-test.c
117
create mode 100644 hw/net/can/trace-events
118
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: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
2
3
The Xilinx ZynqMP CAN controller is developed based on SocketCAN, QEMU CAN bus
3
Add a model of the Xilinx Versal Accelerator RAM (XRAM).
4
implementation. Bus connection and socketCAN connection for each CAN module
4
This is mainly a stub to make firmware happy. The size of
5
can be set through command lines.
5
the RAMs can be probed. The interrupt mask logic is
6
6
modelled but none of the interrups will ever be raised
7
Example for using single CAN:
7
unless injected.
8
-object can-bus,id=canbus0 \
8
9
-machine xlnx-zcu102.canbus0=canbus0 \
9
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0
10
Message-id: 20210308224637.2949533-2-edgar.iglesias@gmail.com
11
12
Example for connecting both CAN to same virtual CAN on host machine:
13
-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
14
-machine xlnx-zcu102.canbus0=canbus0 \
15
-machine xlnx-zcu102.canbus1=canbus1 \
16
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0 \
17
-object can-host-socketcan,id=socketcan1,if=vcan0,canbus=canbus1
18
19
To create virtual CAN on the host machine, please check the QEMU CAN docs:
20
https://github.com/qemu/qemu/blob/master/docs/can.txt
21
22
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
23
Message-id: 1605728926-352690-2-git-send-email-fnu.vikram@xilinx.com
24
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
---
13
---
27
meson.build | 1 +
14
include/hw/misc/xlnx-versal-xramc.h | 97 +++++++++++
28
hw/net/can/trace.h | 1 +
15
hw/misc/xlnx-versal-xramc.c | 253 ++++++++++++++++++++++++++++
29
include/hw/net/xlnx-zynqmp-can.h | 78 ++
16
hw/misc/meson.build | 1 +
30
hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++
17
3 files changed, 351 insertions(+)
31
hw/Kconfig | 1 +
18
create mode 100644 include/hw/misc/xlnx-versal-xramc.h
32
hw/net/can/meson.build | 1 +
19
create mode 100644 hw/misc/xlnx-versal-xramc.c
33
hw/net/can/trace-events | 9 +
20
34
7 files changed, 1252 insertions(+)
21
diff --git a/include/hw/misc/xlnx-versal-xramc.h b/include/hw/misc/xlnx-versal-xramc.h
35
create mode 100644 hw/net/can/trace.h
36
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
37
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
38
create mode 100644 hw/net/can/trace-events
39
40
diff --git a/meson.build b/meson.build
41
index XXXXXXX..XXXXXXX 100644
42
--- a/meson.build
43
+++ b/meson.build
44
@@ -XXX,XX +XXX,XX @@ if have_system
45
'hw/misc',
46
'hw/misc/macio',
47
'hw/net',
48
+ 'hw/net/can',
49
'hw/nvram',
50
'hw/pci',
51
'hw/pci-host',
52
diff --git a/hw/net/can/trace.h b/hw/net/can/trace.h
53
new file mode 100644
22
new file mode 100644
54
index XXXXXXX..XXXXXXX
23
index XXXXXXX..XXXXXXX
55
--- /dev/null
24
--- /dev/null
56
+++ b/hw/net/can/trace.h
25
+++ b/include/hw/misc/xlnx-versal-xramc.h
57
@@ -0,0 +1 @@
26
@@ -XXX,XX +XXX,XX @@
58
+#include "trace/trace-hw_net_can.h"
27
+/*
59
diff --git a/include/hw/net/xlnx-zynqmp-can.h b/include/hw/net/xlnx-zynqmp-can.h
28
+ * QEMU model of the Xilinx XRAM Controller.
29
+ *
30
+ * Copyright (c) 2021 Xilinx Inc.
31
+ * SPDX-License-Identifier: GPL-2.0-or-later
32
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
33
+ */
34
+
35
+#ifndef XLNX_VERSAL_XRAMC_H
36
+#define XLNX_VERSAL_XRAMC_H
37
+
38
+#include "hw/sysbus.h"
39
+#include "hw/register.h"
40
+
41
+#define TYPE_XLNX_XRAM_CTRL "xlnx.versal-xramc"
42
+
43
+#define XLNX_XRAM_CTRL(obj) \
44
+ OBJECT_CHECK(XlnxXramCtrl, (obj), TYPE_XLNX_XRAM_CTRL)
45
+
46
+REG32(XRAM_ERR_CTRL, 0x0)
47
+ FIELD(XRAM_ERR_CTRL, UE_RES, 3, 1)
48
+ FIELD(XRAM_ERR_CTRL, PWR_ERR_RES, 2, 1)
49
+ FIELD(XRAM_ERR_CTRL, PZ_ERR_RES, 1, 1)
50
+ FIELD(XRAM_ERR_CTRL, APB_ERR_RES, 0, 1)
51
+REG32(XRAM_ISR, 0x4)
52
+ FIELD(XRAM_ISR, INV_APB, 0, 1)
53
+REG32(XRAM_IMR, 0x8)
54
+ FIELD(XRAM_IMR, INV_APB, 0, 1)
55
+REG32(XRAM_IEN, 0xc)
56
+ FIELD(XRAM_IEN, INV_APB, 0, 1)
57
+REG32(XRAM_IDS, 0x10)
58
+ FIELD(XRAM_IDS, INV_APB, 0, 1)
59
+REG32(XRAM_ECC_CNTL, 0x14)
60
+ FIELD(XRAM_ECC_CNTL, FI_MODE, 2, 1)
61
+ FIELD(XRAM_ECC_CNTL, DET_ONLY, 1, 1)
62
+ FIELD(XRAM_ECC_CNTL, ECC_ON_OFF, 0, 1)
63
+REG32(XRAM_CLR_EXE, 0x18)
64
+ FIELD(XRAM_CLR_EXE, MON_7, 7, 1)
65
+ FIELD(XRAM_CLR_EXE, MON_6, 6, 1)
66
+ FIELD(XRAM_CLR_EXE, MON_5, 5, 1)
67
+ FIELD(XRAM_CLR_EXE, MON_4, 4, 1)
68
+ FIELD(XRAM_CLR_EXE, MON_3, 3, 1)
69
+ FIELD(XRAM_CLR_EXE, MON_2, 2, 1)
70
+ FIELD(XRAM_CLR_EXE, MON_1, 1, 1)
71
+ FIELD(XRAM_CLR_EXE, MON_0, 0, 1)
72
+REG32(XRAM_CE_FFA, 0x1c)
73
+ FIELD(XRAM_CE_FFA, ADDR, 0, 20)
74
+REG32(XRAM_CE_FFD0, 0x20)
75
+REG32(XRAM_CE_FFD1, 0x24)
76
+REG32(XRAM_CE_FFD2, 0x28)
77
+REG32(XRAM_CE_FFD3, 0x2c)
78
+REG32(XRAM_CE_FFE, 0x30)
79
+ FIELD(XRAM_CE_FFE, SYNDROME, 0, 16)
80
+REG32(XRAM_UE_FFA, 0x34)
81
+ FIELD(XRAM_UE_FFA, ADDR, 0, 20)
82
+REG32(XRAM_UE_FFD0, 0x38)
83
+REG32(XRAM_UE_FFD1, 0x3c)
84
+REG32(XRAM_UE_FFD2, 0x40)
85
+REG32(XRAM_UE_FFD3, 0x44)
86
+REG32(XRAM_UE_FFE, 0x48)
87
+ FIELD(XRAM_UE_FFE, SYNDROME, 0, 16)
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;
111
+ MemoryRegion ram;
112
+ qemu_irq irq;
113
+
114
+ struct {
115
+ uint64_t size;
116
+ unsigned int encoded_size;
117
+ } cfg;
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
60
new file mode 100644
125
new file mode 100644
61
index XXXXXXX..XXXXXXX
126
index XXXXXXX..XXXXXXX
62
--- /dev/null
127
--- /dev/null
63
+++ b/include/hw/net/xlnx-zynqmp-can.h
128
+++ b/hw/misc/xlnx-versal-xramc.c
64
@@ -XXX,XX +XXX,XX @@
129
@@ -XXX,XX +XXX,XX @@
65
+/*
130
+/*
66
+ * QEMU model of the Xilinx ZynqMP CAN controller.
131
+ * QEMU model of the Xilinx XRAM Controller.
67
+ *
132
+ *
68
+ * Copyright (c) 2020 Xilinx Inc.
133
+ * Copyright (c) 2021 Xilinx Inc.
69
+ *
134
+ * SPDX-License-Identifier: GPL-2.0-or-later
70
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
135
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
71
+ *
72
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
73
+ * Pavel Pisa.
74
+ *
75
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
76
+ * of this software and associated documentation files (the "Software"), to deal
77
+ * in the Software without restriction, including without limitation the rights
78
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
79
+ * copies of the Software, and to permit persons to whom the Software is
80
+ * furnished to do so, subject to the following conditions:
81
+ *
82
+ * The above copyright notice and this permission notice shall be included in
83
+ * all copies or substantial portions of the Software.
84
+ *
85
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
87
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
88
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
89
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
90
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
91
+ * THE SOFTWARE.
92
+ */
136
+ */
93
+
137
+
94
+#ifndef XLNX_ZYNQMP_CAN_H
95
+#define XLNX_ZYNQMP_CAN_H
96
+
97
+#include "hw/register.h"
98
+#include "net/can_emu.h"
99
+#include "net/can_host.h"
100
+#include "qemu/fifo32.h"
101
+#include "hw/ptimer.h"
102
+#include "hw/qdev-clock.h"
103
+
104
+#define TYPE_XLNX_ZYNQMP_CAN "xlnx.zynqmp-can"
105
+
106
+#define XLNX_ZYNQMP_CAN(obj) \
107
+ OBJECT_CHECK(XlnxZynqMPCANState, (obj), TYPE_XLNX_ZYNQMP_CAN)
108
+
109
+#define MAX_CAN_CTRLS 2
110
+#define XLNX_ZYNQMP_CAN_R_MAX (0x84 / 4)
111
+#define MAILBOX_CAPACITY 64
112
+#define CAN_TIMER_MAX 0XFFFFUL
113
+#define CAN_DEFAULT_CLOCK (24 * 1000 * 1000)
114
+
115
+/* Each CAN_FRAME will have 4 * 32bit size. */
116
+#define CAN_FRAME_SIZE 4
117
+#define RXFIFO_SIZE (MAILBOX_CAPACITY * CAN_FRAME_SIZE)
118
+
119
+typedef struct XlnxZynqMPCANState {
120
+ SysBusDevice parent_obj;
121
+ MemoryRegion iomem;
122
+
123
+ qemu_irq irq;
124
+
125
+ CanBusClientState bus_client;
126
+ CanBusState *canbus;
127
+
128
+ struct {
129
+ uint32_t ext_clk_freq;
130
+ } cfg;
131
+
132
+ RegisterInfo reg_info[XLNX_ZYNQMP_CAN_R_MAX];
133
+ uint32_t regs[XLNX_ZYNQMP_CAN_R_MAX];
134
+
135
+ Fifo32 rx_fifo;
136
+ Fifo32 tx_fifo;
137
+ Fifo32 txhpb_fifo;
138
+
139
+ ptimer_state *can_timer;
140
+} XlnxZynqMPCANState;
141
+
142
+#endif
143
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
144
new file mode 100644
145
index XXXXXXX..XXXXXXX
146
--- /dev/null
147
+++ b/hw/net/can/xlnx-zynqmp-can.c
148
@@ -XXX,XX +XXX,XX @@
149
+/*
150
+ * QEMU model of the Xilinx ZynqMP CAN controller.
151
+ * This implementation is based on the following datasheet:
152
+ * https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf
153
+ *
154
+ * Copyright (c) 2020 Xilinx Inc.
155
+ *
156
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
157
+ *
158
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
159
+ * Pavel Pisa
160
+ *
161
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
162
+ * of this software and associated documentation files (the "Software"), to deal
163
+ * in the Software without restriction, including without limitation the rights
164
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
165
+ * copies of the Software, and to permit persons to whom the Software is
166
+ * furnished to do so, subject to the following conditions:
167
+ *
168
+ * The above copyright notice and this permission notice shall be included in
169
+ * all copies or substantial portions of the Software.
170
+ *
171
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
172
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
173
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
174
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
175
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
176
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
177
+ * THE SOFTWARE.
178
+ */
179
+
180
+#include "qemu/osdep.h"
138
+#include "qemu/osdep.h"
139
+#include "qemu/units.h"
140
+#include "qapi/error.h"
141
+#include "migration/vmstate.h"
181
+#include "hw/sysbus.h"
142
+#include "hw/sysbus.h"
182
+#include "hw/register.h"
143
+#include "hw/register.h"
144
+#include "hw/qdev-properties.h"
183
+#include "hw/irq.h"
145
+#include "hw/irq.h"
184
+#include "qapi/error.h"
146
+#include "hw/misc/xlnx-versal-xramc.h"
185
+#include "qemu/bitops.h"
147
+
186
+#include "qemu/log.h"
148
+#ifndef XLNX_XRAM_CTRL_ERR_DEBUG
187
+#include "qemu/cutils.h"
149
+#define XLNX_XRAM_CTRL_ERR_DEBUG 0
188
+#include "sysemu/sysemu.h"
189
+#include "migration/vmstate.h"
190
+#include "hw/qdev-properties.h"
191
+#include "net/can_emu.h"
192
+#include "net/can_host.h"
193
+#include "qemu/event_notifier.h"
194
+#include "qom/object_interfaces.h"
195
+#include "hw/net/xlnx-zynqmp-can.h"
196
+#include "trace.h"
197
+
198
+#ifndef XLNX_ZYNQMP_CAN_ERR_DEBUG
199
+#define XLNX_ZYNQMP_CAN_ERR_DEBUG 0
200
+#endif
150
+#endif
201
+
151
+
202
+#define MAX_DLC 8
152
+static void xram_update_irq(XlnxXramCtrl *s)
203
+#undef ERROR
153
+{
204
+
154
+ bool pending = s->regs[R_XRAM_ISR] & ~s->regs[R_XRAM_IMR];
205
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
155
+ qemu_set_irq(s->irq, pending);
206
+ FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1)
156
+}
207
+ FIELD(SOFTWARE_RESET_REGISTER, SRST, 0, 1)
157
+
208
+REG32(MODE_SELECT_REGISTER, 0x4)
158
+static void xram_isr_postw(RegisterInfo *reg, uint64_t val64)
209
+ FIELD(MODE_SELECT_REGISTER, SNOOP, 2, 1)
159
+{
210
+ FIELD(MODE_SELECT_REGISTER, LBACK, 1, 1)
160
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
211
+ FIELD(MODE_SELECT_REGISTER, SLEEP, 0, 1)
161
+ xram_update_irq(s);
212
+REG32(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x8)
162
+}
213
+ FIELD(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, BRP, 0, 8)
163
+
214
+REG32(ARBITRATION_PHASE_BIT_TIMING_REGISTER, 0xc)
164
+static uint64_t xram_ien_prew(RegisterInfo *reg, uint64_t val64)
215
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, SJW, 7, 2)
165
+{
216
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 4, 3)
166
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
217
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 4)
167
+ uint32_t val = val64;
218
+REG32(ERROR_COUNTER_REGISTER, 0x10)
168
+
219
+ FIELD(ERROR_COUNTER_REGISTER, REC, 8, 8)
169
+ s->regs[R_XRAM_IMR] &= ~val;
220
+ FIELD(ERROR_COUNTER_REGISTER, TEC, 0, 8)
170
+ xram_update_irq(s);
221
+REG32(ERROR_STATUS_REGISTER, 0x14)
171
+ return 0;
222
+ FIELD(ERROR_STATUS_REGISTER, ACKER, 4, 1)
172
+}
223
+ FIELD(ERROR_STATUS_REGISTER, BERR, 3, 1)
173
+
224
+ FIELD(ERROR_STATUS_REGISTER, STER, 2, 1)
174
+static uint64_t xram_ids_prew(RegisterInfo *reg, uint64_t val64)
225
+ FIELD(ERROR_STATUS_REGISTER, FMER, 1, 1)
175
+{
226
+ FIELD(ERROR_STATUS_REGISTER, CRCER, 0, 1)
176
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
227
+REG32(STATUS_REGISTER, 0x18)
177
+ uint32_t val = val64;
228
+ FIELD(STATUS_REGISTER, SNOOP, 12, 1)
178
+
229
+ FIELD(STATUS_REGISTER, ACFBSY, 11, 1)
179
+ s->regs[R_XRAM_IMR] |= val;
230
+ FIELD(STATUS_REGISTER, TXFLL, 10, 1)
180
+ xram_update_irq(s);
231
+ FIELD(STATUS_REGISTER, TXBFLL, 9, 1)
181
+ return 0;
232
+ FIELD(STATUS_REGISTER, ESTAT, 7, 2)
182
+}
233
+ FIELD(STATUS_REGISTER, ERRWRN, 6, 1)
183
+
234
+ FIELD(STATUS_REGISTER, BBSY, 5, 1)
184
+static const RegisterAccessInfo xram_ctrl_regs_info[] = {
235
+ FIELD(STATUS_REGISTER, BIDLE, 4, 1)
185
+ { .name = "XRAM_ERR_CTRL", .addr = A_XRAM_ERR_CTRL,
236
+ FIELD(STATUS_REGISTER, NORMAL, 3, 1)
186
+ .reset = 0xf,
237
+ FIELD(STATUS_REGISTER, SLEEP, 2, 1)
187
+ .rsvd = 0xfffffff0,
238
+ FIELD(STATUS_REGISTER, LBACK, 1, 1)
188
+ },{ .name = "XRAM_ISR", .addr = A_XRAM_ISR,
239
+ FIELD(STATUS_REGISTER, CONFIG, 0, 1)
189
+ .rsvd = 0xfffff800,
240
+REG32(INTERRUPT_STATUS_REGISTER, 0x1c)
190
+ .w1c = 0x7ff,
241
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFEMP, 14, 1)
191
+ .post_write = xram_isr_postw,
242
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFWMEMP, 13, 1)
192
+ },{ .name = "XRAM_IMR", .addr = A_XRAM_IMR,
243
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL, 12, 1)
193
+ .reset = 0x7ff,
244
+ FIELD(INTERRUPT_STATUS_REGISTER, WKUP, 11, 1)
194
+ .rsvd = 0xfffff800,
245
+ FIELD(INTERRUPT_STATUS_REGISTER, SLP, 10, 1)
195
+ .ro = 0x7ff,
246
+ FIELD(INTERRUPT_STATUS_REGISTER, BSOFF, 9, 1)
196
+ },{ .name = "XRAM_IEN", .addr = A_XRAM_IEN,
247
+ FIELD(INTERRUPT_STATUS_REGISTER, ERROR, 8, 1)
197
+ .rsvd = 0xfffff800,
248
+ FIELD(INTERRUPT_STATUS_REGISTER, RXNEMP, 7, 1)
198
+ .pre_write = xram_ien_prew,
249
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOFLW, 6, 1)
199
+ },{ .name = "XRAM_IDS", .addr = A_XRAM_IDS,
250
+ FIELD(INTERRUPT_STATUS_REGISTER, RXUFLW, 5, 1)
200
+ .rsvd = 0xfffff800,
251
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1)
201
+ .pre_write = xram_ids_prew,
252
+ FIELD(INTERRUPT_STATUS_REGISTER, TXBFLL, 3, 1)
202
+ },{ .name = "XRAM_ECC_CNTL", .addr = A_XRAM_ECC_CNTL,
253
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFLL, 2, 1)
203
+ .rsvd = 0xfffffff8,
254
+ FIELD(INTERRUPT_STATUS_REGISTER, TXOK, 1, 1)
204
+ },{ .name = "XRAM_CLR_EXE", .addr = A_XRAM_CLR_EXE,
255
+ FIELD(INTERRUPT_STATUS_REGISTER, ARBLST, 0, 1)
205
+ .rsvd = 0xffffff00,
256
+REG32(INTERRUPT_ENABLE_REGISTER, 0x20)
206
+ },{ .name = "XRAM_CE_FFA", .addr = A_XRAM_CE_FFA,
257
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFEMP, 14, 1)
207
+ .rsvd = 0xfff00000,
258
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFWMEMP, 13, 1)
208
+ .ro = 0xfffff,
259
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL, 12, 1)
209
+ },{ .name = "XRAM_CE_FFD0", .addr = A_XRAM_CE_FFD0,
260
+ FIELD(INTERRUPT_ENABLE_REGISTER, EWKUP, 11, 1)
210
+ .ro = 0xffffffff,
261
+ FIELD(INTERRUPT_ENABLE_REGISTER, ESLP, 10, 1)
211
+ },{ .name = "XRAM_CE_FFD1", .addr = A_XRAM_CE_FFD1,
262
+ FIELD(INTERRUPT_ENABLE_REGISTER, EBSOFF, 9, 1)
212
+ .ro = 0xffffffff,
263
+ FIELD(INTERRUPT_ENABLE_REGISTER, EERROR, 8, 1)
213
+ },{ .name = "XRAM_CE_FFD2", .addr = A_XRAM_CE_FFD2,
264
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXNEMP, 7, 1)
214
+ .ro = 0xffffffff,
265
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOFLW, 6, 1)
215
+ },{ .name = "XRAM_CE_FFD3", .addr = A_XRAM_CE_FFD3,
266
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXUFLW, 5, 1)
216
+ .ro = 0xffffffff,
267
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1)
217
+ },{ .name = "XRAM_CE_FFE", .addr = A_XRAM_CE_FFE,
268
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXBFLL, 3, 1)
218
+ .rsvd = 0xffff0000,
269
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFLL, 2, 1)
219
+ .ro = 0xffff,
270
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1)
220
+ },{ .name = "XRAM_UE_FFA", .addr = A_XRAM_UE_FFA,
271
+ FIELD(INTERRUPT_ENABLE_REGISTER, EARBLST, 0, 1)
221
+ .rsvd = 0xfff00000,
272
+REG32(INTERRUPT_CLEAR_REGISTER, 0x24)
222
+ .ro = 0xfffff,
273
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFEMP, 14, 1)
223
+ },{ .name = "XRAM_UE_FFD0", .addr = A_XRAM_UE_FFD0,
274
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFWMEMP, 13, 1)
224
+ .ro = 0xffffffff,
275
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL, 12, 1)
225
+ },{ .name = "XRAM_UE_FFD1", .addr = A_XRAM_UE_FFD1,
276
+ FIELD(INTERRUPT_CLEAR_REGISTER, CWKUP, 11, 1)
226
+ .ro = 0xffffffff,
277
+ FIELD(INTERRUPT_CLEAR_REGISTER, CSLP, 10, 1)
227
+ },{ .name = "XRAM_UE_FFD2", .addr = A_XRAM_UE_FFD2,
278
+ FIELD(INTERRUPT_CLEAR_REGISTER, CBSOFF, 9, 1)
228
+ .ro = 0xffffffff,
279
+ FIELD(INTERRUPT_CLEAR_REGISTER, CERROR, 8, 1)
229
+ },{ .name = "XRAM_UE_FFD3", .addr = A_XRAM_UE_FFD3,
280
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXNEMP, 7, 1)
230
+ .ro = 0xffffffff,
281
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOFLW, 6, 1)
231
+ },{ .name = "XRAM_UE_FFE", .addr = A_XRAM_UE_FFE,
282
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXUFLW, 5, 1)
232
+ .rsvd = 0xffff0000,
283
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1)
233
+ .ro = 0xffff,
284
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXBFLL, 3, 1)
234
+ },{ .name = "XRAM_FI_D0", .addr = A_XRAM_FI_D0,
285
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFLL, 2, 1)
235
+ },{ .name = "XRAM_FI_D1", .addr = A_XRAM_FI_D1,
286
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1)
236
+ },{ .name = "XRAM_FI_D2", .addr = A_XRAM_FI_D2,
287
+ FIELD(INTERRUPT_CLEAR_REGISTER, CARBLST, 0, 1)
237
+ },{ .name = "XRAM_FI_D3", .addr = A_XRAM_FI_D3,
288
+REG32(TIMESTAMP_REGISTER, 0x28)
238
+ },{ .name = "XRAM_FI_SY", .addr = A_XRAM_FI_SY,
289
+ FIELD(TIMESTAMP_REGISTER, CTS, 0, 1)
239
+ .rsvd = 0xffff0000,
290
+REG32(WIR, 0x2c)
240
+ },{ .name = "XRAM_RMW_UE_FFA", .addr = A_XRAM_RMW_UE_FFA,
291
+ FIELD(WIR, EW, 8, 8)
241
+ .rsvd = 0xfff00000,
292
+ FIELD(WIR, FW, 0, 8)
242
+ .ro = 0xfffff,
293
+REG32(TXFIFO_ID, 0x30)
243
+ },{ .name = "XRAM_FI_CNTR", .addr = A_XRAM_FI_CNTR,
294
+ FIELD(TXFIFO_ID, IDH, 21, 11)
244
+ .rsvd = 0xff000000,
295
+ FIELD(TXFIFO_ID, SRRRTR, 20, 1)
245
+ },{ .name = "XRAM_IMP", .addr = A_XRAM_IMP,
296
+ FIELD(TXFIFO_ID, IDE, 19, 1)
246
+ .reset = 0x4,
297
+ FIELD(TXFIFO_ID, IDL, 1, 18)
247
+ .rsvd = 0xfffffff0,
298
+ FIELD(TXFIFO_ID, RTR, 0, 1)
248
+ .ro = 0xf,
299
+REG32(TXFIFO_DLC, 0x34)
249
+ },{ .name = "XRAM_PRDY_DBG", .addr = A_XRAM_PRDY_DBG,
300
+ FIELD(TXFIFO_DLC, DLC, 28, 4)
250
+ .reset = 0xffff,
301
+REG32(TXFIFO_DATA1, 0x38)
251
+ .rsvd = 0xffff0000,
302
+ FIELD(TXFIFO_DATA1, DB0, 24, 8)
252
+ .ro = 0xffff,
303
+ FIELD(TXFIFO_DATA1, DB1, 16, 8)
253
+ },{ .name = "XRAM_SAFETY_CHK", .addr = A_XRAM_SAFETY_CHK,
304
+ FIELD(TXFIFO_DATA1, DB2, 8, 8)
305
+ FIELD(TXFIFO_DATA1, DB3, 0, 8)
306
+REG32(TXFIFO_DATA2, 0x3c)
307
+ FIELD(TXFIFO_DATA2, DB4, 24, 8)
308
+ FIELD(TXFIFO_DATA2, DB5, 16, 8)
309
+ FIELD(TXFIFO_DATA2, DB6, 8, 8)
310
+ FIELD(TXFIFO_DATA2, DB7, 0, 8)
311
+REG32(TXHPB_ID, 0x40)
312
+ FIELD(TXHPB_ID, IDH, 21, 11)
313
+ FIELD(TXHPB_ID, SRRRTR, 20, 1)
314
+ FIELD(TXHPB_ID, IDE, 19, 1)
315
+ FIELD(TXHPB_ID, IDL, 1, 18)
316
+ FIELD(TXHPB_ID, RTR, 0, 1)
317
+REG32(TXHPB_DLC, 0x44)
318
+ FIELD(TXHPB_DLC, DLC, 28, 4)
319
+REG32(TXHPB_DATA1, 0x48)
320
+ FIELD(TXHPB_DATA1, DB0, 24, 8)
321
+ FIELD(TXHPB_DATA1, DB1, 16, 8)
322
+ FIELD(TXHPB_DATA1, DB2, 8, 8)
323
+ FIELD(TXHPB_DATA1, DB3, 0, 8)
324
+REG32(TXHPB_DATA2, 0x4c)
325
+ FIELD(TXHPB_DATA2, DB4, 24, 8)
326
+ FIELD(TXHPB_DATA2, DB5, 16, 8)
327
+ FIELD(TXHPB_DATA2, DB6, 8, 8)
328
+ FIELD(TXHPB_DATA2, DB7, 0, 8)
329
+REG32(RXFIFO_ID, 0x50)
330
+ FIELD(RXFIFO_ID, IDH, 21, 11)
331
+ FIELD(RXFIFO_ID, SRRRTR, 20, 1)
332
+ FIELD(RXFIFO_ID, IDE, 19, 1)
333
+ FIELD(RXFIFO_ID, IDL, 1, 18)
334
+ FIELD(RXFIFO_ID, RTR, 0, 1)
335
+REG32(RXFIFO_DLC, 0x54)
336
+ FIELD(RXFIFO_DLC, DLC, 28, 4)
337
+ FIELD(RXFIFO_DLC, RXT, 0, 16)
338
+REG32(RXFIFO_DATA1, 0x58)
339
+ FIELD(RXFIFO_DATA1, DB0, 24, 8)
340
+ FIELD(RXFIFO_DATA1, DB1, 16, 8)
341
+ FIELD(RXFIFO_DATA1, DB2, 8, 8)
342
+ FIELD(RXFIFO_DATA1, DB3, 0, 8)
343
+REG32(RXFIFO_DATA2, 0x5c)
344
+ FIELD(RXFIFO_DATA2, DB4, 24, 8)
345
+ FIELD(RXFIFO_DATA2, DB5, 16, 8)
346
+ FIELD(RXFIFO_DATA2, DB6, 8, 8)
347
+ FIELD(RXFIFO_DATA2, DB7, 0, 8)
348
+REG32(AFR, 0x60)
349
+ FIELD(AFR, UAF4, 3, 1)
350
+ FIELD(AFR, UAF3, 2, 1)
351
+ FIELD(AFR, UAF2, 1, 1)
352
+ FIELD(AFR, UAF1, 0, 1)
353
+REG32(AFMR1, 0x64)
354
+ FIELD(AFMR1, AMIDH, 21, 11)
355
+ FIELD(AFMR1, AMSRR, 20, 1)
356
+ FIELD(AFMR1, AMIDE, 19, 1)
357
+ FIELD(AFMR1, AMIDL, 1, 18)
358
+ FIELD(AFMR1, AMRTR, 0, 1)
359
+REG32(AFIR1, 0x68)
360
+ FIELD(AFIR1, AIIDH, 21, 11)
361
+ FIELD(AFIR1, AISRR, 20, 1)
362
+ FIELD(AFIR1, AIIDE, 19, 1)
363
+ FIELD(AFIR1, AIIDL, 1, 18)
364
+ FIELD(AFIR1, AIRTR, 0, 1)
365
+REG32(AFMR2, 0x6c)
366
+ FIELD(AFMR2, AMIDH, 21, 11)
367
+ FIELD(AFMR2, AMSRR, 20, 1)
368
+ FIELD(AFMR2, AMIDE, 19, 1)
369
+ FIELD(AFMR2, AMIDL, 1, 18)
370
+ FIELD(AFMR2, AMRTR, 0, 1)
371
+REG32(AFIR2, 0x70)
372
+ FIELD(AFIR2, AIIDH, 21, 11)
373
+ FIELD(AFIR2, AISRR, 20, 1)
374
+ FIELD(AFIR2, AIIDE, 19, 1)
375
+ FIELD(AFIR2, AIIDL, 1, 18)
376
+ FIELD(AFIR2, AIRTR, 0, 1)
377
+REG32(AFMR3, 0x74)
378
+ FIELD(AFMR3, AMIDH, 21, 11)
379
+ FIELD(AFMR3, AMSRR, 20, 1)
380
+ FIELD(AFMR3, AMIDE, 19, 1)
381
+ FIELD(AFMR3, AMIDL, 1, 18)
382
+ FIELD(AFMR3, AMRTR, 0, 1)
383
+REG32(AFIR3, 0x78)
384
+ FIELD(AFIR3, AIIDH, 21, 11)
385
+ FIELD(AFIR3, AISRR, 20, 1)
386
+ FIELD(AFIR3, AIIDE, 19, 1)
387
+ FIELD(AFIR3, AIIDL, 1, 18)
388
+ FIELD(AFIR3, AIRTR, 0, 1)
389
+REG32(AFMR4, 0x7c)
390
+ FIELD(AFMR4, AMIDH, 21, 11)
391
+ FIELD(AFMR4, AMSRR, 20, 1)
392
+ FIELD(AFMR4, AMIDE, 19, 1)
393
+ FIELD(AFMR4, AMIDL, 1, 18)
394
+ FIELD(AFMR4, AMRTR, 0, 1)
395
+REG32(AFIR4, 0x80)
396
+ FIELD(AFIR4, AIIDH, 21, 11)
397
+ FIELD(AFIR4, AISRR, 20, 1)
398
+ FIELD(AFIR4, AIIDE, 19, 1)
399
+ FIELD(AFIR4, AIIDL, 1, 18)
400
+ FIELD(AFIR4, AIRTR, 0, 1)
401
+
402
+static void can_update_irq(XlnxZynqMPCANState *s)
403
+{
404
+ uint32_t irq;
405
+
406
+ /* Watermark register interrupts. */
407
+ if ((fifo32_num_free(&s->tx_fifo) / CAN_FRAME_SIZE) >
408
+ ARRAY_FIELD_EX32(s->regs, WIR, EW)) {
409
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFWMEMP, 1);
410
+ }
254
+ }
411
+
255
+};
412
+ if ((fifo32_num_used(&s->rx_fifo) / CAN_FRAME_SIZE) >
256
+
413
+ ARRAY_FIELD_EX32(s->regs, WIR, FW)) {
257
+static void xram_ctrl_reset_enter(Object *obj, ResetType type)
414
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL, 1);
258
+{
259
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
260
+ unsigned int i;
261
+
262
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
263
+ register_reset(&s->regs_info[i]);
415
+ }
264
+ }
416
+
265
+
417
+ /* RX Interrupts. */
266
+ ARRAY_FIELD_DP32(s->regs, XRAM_IMP, SIZE, s->cfg.encoded_size);
418
+ if (fifo32_num_used(&s->rx_fifo) >= CAN_FRAME_SIZE) {
267
+}
419
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXNEMP, 1);
268
+
420
+ }
269
+static void xram_ctrl_reset_hold(Object *obj)
421
+
270
+{
422
+ /* TX interrupts. */
271
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
423
+ if (fifo32_is_empty(&s->tx_fifo)) {
272
+
424
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFEMP, 1);
273
+ xram_update_irq(s);
425
+ }
274
+}
426
+
275
+
427
+ if (fifo32_is_full(&s->tx_fifo)) {
276
+static const MemoryRegionOps xram_ctrl_ops = {
428
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFLL, 1);
429
+ }
430
+
431
+ if (fifo32_is_full(&s->txhpb_fifo)) {
432
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXBFLL, 1);
433
+ }
434
+
435
+ irq = s->regs[R_INTERRUPT_STATUS_REGISTER];
436
+ irq &= s->regs[R_INTERRUPT_ENABLE_REGISTER];
437
+
438
+ trace_xlnx_can_update_irq(s->regs[R_INTERRUPT_STATUS_REGISTER],
439
+ s->regs[R_INTERRUPT_ENABLE_REGISTER], irq);
440
+ qemu_set_irq(s->irq, irq);
441
+}
442
+
443
+static void can_ier_post_write(RegisterInfo *reg, uint64_t val)
444
+{
445
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
446
+
447
+ can_update_irq(s);
448
+}
449
+
450
+static uint64_t can_icr_pre_write(RegisterInfo *reg, uint64_t val)
451
+{
452
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
453
+
454
+ s->regs[R_INTERRUPT_STATUS_REGISTER] &= ~val;
455
+ can_update_irq(s);
456
+
457
+ return 0;
458
+}
459
+
460
+static void can_config_reset(XlnxZynqMPCANState *s)
461
+{
462
+ /* Reset all the configuration registers. */
463
+ register_reset(&s->reg_info[R_SOFTWARE_RESET_REGISTER]);
464
+ register_reset(&s->reg_info[R_MODE_SELECT_REGISTER]);
465
+ register_reset(
466
+ &s->reg_info[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER]);
467
+ register_reset(&s->reg_info[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER]);
468
+ register_reset(&s->reg_info[R_STATUS_REGISTER]);
469
+ register_reset(&s->reg_info[R_INTERRUPT_STATUS_REGISTER]);
470
+ register_reset(&s->reg_info[R_INTERRUPT_ENABLE_REGISTER]);
471
+ register_reset(&s->reg_info[R_INTERRUPT_CLEAR_REGISTER]);
472
+ register_reset(&s->reg_info[R_WIR]);
473
+}
474
+
475
+static void can_config_mode(XlnxZynqMPCANState *s)
476
+{
477
+ register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]);
478
+ register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]);
479
+
480
+ /* Put XlnxZynqMPCAN in configuration mode. */
481
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1);
482
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0);
483
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0);
484
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0);
485
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR, 0);
486
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 0);
487
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0);
488
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0);
489
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0);
490
+
491
+ can_update_irq(s);
492
+}
493
+
494
+static void update_status_register_mode_bits(XlnxZynqMPCANState *s)
495
+{
496
+ bool sleep_status = ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP);
497
+ bool sleep_mode = ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP);
498
+ /* Wake up interrupt bit. */
499
+ bool wakeup_irq_val = sleep_status && (sleep_mode == 0);
500
+ /* Sleep interrupt bit. */
501
+ bool sleep_irq_val = sleep_mode && (sleep_status == 0);
502
+
503
+ /* Clear previous core mode status bits. */
504
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 0);
505
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 0);
506
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 0);
507
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 0);
508
+
509
+ /* set current mode bit and generate irqs accordingly. */
510
+ if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, LBACK)) {
511
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 1);
512
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP)) {
513
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 1);
514
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP,
515
+ sleep_irq_val);
516
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
517
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 1);
518
+ } else {
519
+ /*
520
+ * If all bits are zero then XlnxZynqMPCAN is set in normal mode.
521
+ */
522
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 1);
523
+ /* Set wakeup interrupt bit. */
524
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP,
525
+ wakeup_irq_val);
526
+ }
527
+
528
+ can_update_irq(s);
529
+}
530
+
531
+static void can_exit_sleep_mode(XlnxZynqMPCANState *s)
532
+{
533
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, 0);
534
+ update_status_register_mode_bits(s);
535
+}
536
+
537
+static void generate_frame(qemu_can_frame *frame, uint32_t *data)
538
+{
539
+ frame->can_id = data[0];
540
+ frame->can_dlc = FIELD_EX32(data[1], TXFIFO_DLC, DLC);
541
+
542
+ frame->data[0] = FIELD_EX32(data[2], TXFIFO_DATA1, DB3);
543
+ frame->data[1] = FIELD_EX32(data[2], TXFIFO_DATA1, DB2);
544
+ frame->data[2] = FIELD_EX32(data[2], TXFIFO_DATA1, DB1);
545
+ frame->data[3] = FIELD_EX32(data[2], TXFIFO_DATA1, DB0);
546
+
547
+ frame->data[4] = FIELD_EX32(data[3], TXFIFO_DATA2, DB7);
548
+ frame->data[5] = FIELD_EX32(data[3], TXFIFO_DATA2, DB6);
549
+ frame->data[6] = FIELD_EX32(data[3], TXFIFO_DATA2, DB5);
550
+ frame->data[7] = FIELD_EX32(data[3], TXFIFO_DATA2, DB4);
551
+}
552
+
553
+static bool tx_ready_check(XlnxZynqMPCANState *s)
554
+{
555
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
556
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
557
+
558
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
559
+ " data while controller is in reset mode.\n",
560
+ path);
561
+ return false;
562
+ }
563
+
564
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
565
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
566
+
567
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
568
+ " data while controller is in configuration mode. Reset"
569
+ " the core so operations can start fresh.\n",
570
+ path);
571
+ return false;
572
+ }
573
+
574
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
575
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
576
+
577
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
578
+ " data while controller is in SNOOP MODE.\n",
579
+ path);
580
+ return false;
581
+ }
582
+
583
+ return true;
584
+}
585
+
586
+static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
587
+{
588
+ qemu_can_frame frame;
589
+ uint32_t data[CAN_FRAME_SIZE];
590
+ int i;
591
+ bool can_tx = tx_ready_check(s);
592
+
593
+ if (!can_tx) {
594
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
595
+
596
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is not enabled for data"
597
+ " transfer.\n", path);
598
+ can_update_irq(s);
599
+ return;
600
+ }
601
+
602
+ while (!fifo32_is_empty(fifo)) {
603
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
604
+ data[i] = fifo32_pop(fifo);
605
+ }
606
+
607
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
608
+ /*
609
+ * Controller is in loopback. In Loopback mode, the CAN core
610
+ * transmits a recessive bitstream on to the XlnxZynqMPCAN Bus.
611
+ * Any message transmitted is looped back to the RX line and
612
+ * acknowledged. The XlnxZynqMPCAN core receives any message
613
+ * that it transmits.
614
+ */
615
+ if (fifo32_is_full(&s->rx_fifo)) {
616
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
617
+ } else {
618
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
619
+ fifo32_push(&s->rx_fifo, data[i]);
620
+ }
621
+
622
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
623
+ }
624
+ } else {
625
+ /* Normal mode Tx. */
626
+ generate_frame(&frame, data);
627
+
628
+ trace_xlnx_can_tx_data(frame.can_id, frame.can_dlc,
629
+ frame.data[0], frame.data[1],
630
+ frame.data[2], frame.data[3],
631
+ frame.data[4], frame.data[5],
632
+ frame.data[6], frame.data[7]);
633
+ can_bus_client_send(&s->bus_client, &frame, 1);
634
+ }
635
+ }
636
+
637
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1);
638
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, TXBFLL, 0);
639
+
640
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) {
641
+ can_exit_sleep_mode(s);
642
+ }
643
+
644
+ can_update_irq(s);
645
+}
646
+
647
+static uint64_t can_srr_pre_write(RegisterInfo *reg, uint64_t val)
648
+{
649
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
650
+
651
+ ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN,
652
+ FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN));
653
+
654
+ if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) {
655
+ trace_xlnx_can_reset(val);
656
+
657
+ /* First, core will do software reset then will enter in config mode. */
658
+ can_config_reset(s);
659
+ }
660
+
661
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
662
+ can_config_mode(s);
663
+ } else {
664
+ /*
665
+ * Leave config mode. Now XlnxZynqMPCAN core will enter normal,
666
+ * sleep, snoop or loopback mode depending upon LBACK, SLEEP, SNOOP
667
+ * register states.
668
+ */
669
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0);
670
+
671
+ ptimer_transaction_begin(s->can_timer);
672
+ ptimer_set_count(s->can_timer, 0);
673
+ ptimer_transaction_commit(s->can_timer);
674
+
675
+ /* XlnxZynqMPCAN is out of config mode. It will send pending data. */
676
+ transfer_fifo(s, &s->txhpb_fifo);
677
+ transfer_fifo(s, &s->tx_fifo);
678
+ }
679
+
680
+ update_status_register_mode_bits(s);
681
+
682
+ return s->regs[R_SOFTWARE_RESET_REGISTER];
683
+}
684
+
685
+static uint64_t can_msr_pre_write(RegisterInfo *reg, uint64_t val)
686
+{
687
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
688
+ uint8_t multi_mode;
689
+
690
+ /*
691
+ * Multiple mode set check. This is done to make sure user doesn't set
692
+ * multiple modes.
693
+ */
694
+ multi_mode = FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK) +
695
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP) +
696
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP);
697
+
698
+ if (multi_mode > 1) {
699
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
700
+
701
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to config"
702
+ " several modes simultaneously. One mode will be selected"
703
+ " according to their priority: LBACK > SLEEP > SNOOP.\n",
704
+ path);
705
+ }
706
+
707
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
708
+ /* We are in configuration mode, any mode can be selected. */
709
+ s->regs[R_MODE_SELECT_REGISTER] = val;
710
+ } else {
711
+ bool sleep_mode_bit = FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP);
712
+
713
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, sleep_mode_bit);
714
+
715
+ if (FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK)) {
716
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
717
+
718
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
719
+ " LBACK mode without setting CEN bit as 0.\n",
720
+ path);
721
+ } else if (FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP)) {
722
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
723
+
724
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
725
+ " SNOOP mode without setting CEN bit as 0.\n",
726
+ path);
727
+ }
728
+
729
+ update_status_register_mode_bits(s);
730
+ }
731
+
732
+ return s->regs[R_MODE_SELECT_REGISTER];
733
+}
734
+
735
+static uint64_t can_brpr_pre_write(RegisterInfo *reg, uint64_t val)
736
+{
737
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
738
+
739
+ /* Only allow writes when in config mode. */
740
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
741
+ return s->regs[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER];
742
+ }
743
+
744
+ return val;
745
+}
746
+
747
+static uint64_t can_btr_pre_write(RegisterInfo *reg, uint64_t val)
748
+{
749
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
750
+
751
+ /* Only allow writes when in config mode. */
752
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
753
+ return s->regs[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER];
754
+ }
755
+
756
+ return val;
757
+}
758
+
759
+static uint64_t can_tcr_pre_write(RegisterInfo *reg, uint64_t val)
760
+{
761
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
762
+
763
+ if (FIELD_EX32(val, TIMESTAMP_REGISTER, CTS)) {
764
+ ptimer_transaction_begin(s->can_timer);
765
+ ptimer_set_count(s->can_timer, 0);
766
+ ptimer_transaction_commit(s->can_timer);
767
+ }
768
+
769
+ return 0;
770
+}
771
+
772
+static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame)
773
+{
774
+ bool filter_pass = false;
775
+ uint16_t timestamp = 0;
776
+
777
+ /* If no filter is enabled. Message will be stored in FIFO. */
778
+ if (!((ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) |
779
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) |
780
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) |
781
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)))) {
782
+ filter_pass = true;
783
+ }
784
+
785
+ /*
786
+ * Messages that pass any of the acceptance filters will be stored in
787
+ * the RX FIFO.
788
+ */
789
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) {
790
+ uint32_t id_masked = s->regs[R_AFMR1] & frame->can_id;
791
+ uint32_t filter_id_masked = s->regs[R_AFMR1] & s->regs[R_AFIR1];
792
+
793
+ if (filter_id_masked == id_masked) {
794
+ filter_pass = true;
795
+ }
796
+ }
797
+
798
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) {
799
+ uint32_t id_masked = s->regs[R_AFMR2] & frame->can_id;
800
+ uint32_t filter_id_masked = s->regs[R_AFMR2] & s->regs[R_AFIR2];
801
+
802
+ if (filter_id_masked == id_masked) {
803
+ filter_pass = true;
804
+ }
805
+ }
806
+
807
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) {
808
+ uint32_t id_masked = s->regs[R_AFMR3] & frame->can_id;
809
+ uint32_t filter_id_masked = s->regs[R_AFMR3] & s->regs[R_AFIR3];
810
+
811
+ if (filter_id_masked == id_masked) {
812
+ filter_pass = true;
813
+ }
814
+ }
815
+
816
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
817
+ uint32_t id_masked = s->regs[R_AFMR4] & frame->can_id;
818
+ uint32_t filter_id_masked = s->regs[R_AFMR4] & s->regs[R_AFIR4];
819
+
820
+ if (filter_id_masked == id_masked) {
821
+ filter_pass = true;
822
+ }
823
+ }
824
+
825
+ if (!filter_pass) {
826
+ trace_xlnx_can_rx_fifo_filter_reject(frame->can_id, frame->can_dlc);
827
+ return;
828
+ }
829
+
830
+ /* Store the message in fifo if it passed through any of the filters. */
831
+ if (filter_pass && frame->can_dlc <= MAX_DLC) {
832
+
833
+ if (fifo32_is_full(&s->rx_fifo)) {
834
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
835
+ } else {
836
+ timestamp = CAN_TIMER_MAX - ptimer_get_count(s->can_timer);
837
+
838
+ fifo32_push(&s->rx_fifo, frame->can_id);
839
+
840
+ fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DLC_DLC_SHIFT,
841
+ R_RXFIFO_DLC_DLC_LENGTH,
842
+ frame->can_dlc) |
843
+ deposit32(0, R_RXFIFO_DLC_RXT_SHIFT,
844
+ R_RXFIFO_DLC_RXT_LENGTH,
845
+ timestamp));
846
+
847
+ /* First 32 bit of the data. */
848
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA1_DB3_SHIFT,
849
+ R_TXFIFO_DATA1_DB3_LENGTH,
850
+ frame->data[0]) |
851
+ deposit32(0, R_TXFIFO_DATA1_DB2_SHIFT,
852
+ R_TXFIFO_DATA1_DB2_LENGTH,
853
+ frame->data[1]) |
854
+ deposit32(0, R_TXFIFO_DATA1_DB1_SHIFT,
855
+ R_TXFIFO_DATA1_DB1_LENGTH,
856
+ frame->data[2]) |
857
+ deposit32(0, R_TXFIFO_DATA1_DB0_SHIFT,
858
+ R_TXFIFO_DATA1_DB0_LENGTH,
859
+ frame->data[3]));
860
+ /* Last 32 bit of the data. */
861
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA2_DB7_SHIFT,
862
+ R_TXFIFO_DATA2_DB7_LENGTH,
863
+ frame->data[4]) |
864
+ deposit32(0, R_TXFIFO_DATA2_DB6_SHIFT,
865
+ R_TXFIFO_DATA2_DB6_LENGTH,
866
+ frame->data[5]) |
867
+ deposit32(0, R_TXFIFO_DATA2_DB5_SHIFT,
868
+ R_TXFIFO_DATA2_DB5_LENGTH,
869
+ frame->data[6]) |
870
+ deposit32(0, R_TXFIFO_DATA2_DB4_SHIFT,
871
+ R_TXFIFO_DATA2_DB4_LENGTH,
872
+ frame->data[7]));
873
+
874
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
875
+ trace_xlnx_can_rx_data(frame->can_id, frame->can_dlc,
876
+ frame->data[0], frame->data[1],
877
+ frame->data[2], frame->data[3],
878
+ frame->data[4], frame->data[5],
879
+ frame->data[6], frame->data[7]);
880
+ }
881
+
882
+ can_update_irq(s);
883
+ }
884
+}
885
+
886
+static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val)
887
+{
888
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
889
+
890
+ if (!fifo32_is_empty(&s->rx_fifo)) {
891
+ val = fifo32_pop(&s->rx_fifo);
892
+ } else {
893
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1);
894
+ }
895
+
896
+ can_update_irq(s);
897
+ return val;
898
+}
899
+
900
+static void can_filter_enable_post_write(RegisterInfo *reg, uint64_t val)
901
+{
902
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
903
+
904
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1) &&
905
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF2) &&
906
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF3) &&
907
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
908
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 1);
909
+ } else {
910
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 0);
911
+ }
912
+}
913
+
914
+static uint64_t can_filter_mask_pre_write(RegisterInfo *reg, uint64_t val)
915
+{
916
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
917
+ uint32_t reg_idx = (reg->access->addr) / 4;
918
+ uint32_t filter_number = (reg_idx - R_AFMR1) / 2;
919
+
920
+ /* modify an acceptance filter, the corresponding UAF bit should be '0'. */
921
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
922
+ s->regs[reg_idx] = val;
923
+
924
+ trace_xlnx_can_filter_mask_pre_write(filter_number, s->regs[reg_idx]);
925
+ } else {
926
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
927
+
928
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
929
+ " mask is not set as corresponding UAF bit is not 0.\n",
930
+ path, filter_number + 1);
931
+ }
932
+
933
+ return s->regs[reg_idx];
934
+}
935
+
936
+static uint64_t can_filter_id_pre_write(RegisterInfo *reg, uint64_t val)
937
+{
938
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
939
+ uint32_t reg_idx = (reg->access->addr) / 4;
940
+ uint32_t filter_number = (reg_idx - R_AFIR1) / 2;
941
+
942
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
943
+ s->regs[reg_idx] = val;
944
+
945
+ trace_xlnx_can_filter_id_pre_write(filter_number, s->regs[reg_idx]);
946
+ } else {
947
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
948
+
949
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
950
+ " id is not set as corresponding UAF bit is not 0.\n",
951
+ path, filter_number + 1);
952
+ }
953
+
954
+ return s->regs[reg_idx];
955
+}
956
+
957
+static void can_tx_post_write(RegisterInfo *reg, uint64_t val)
958
+{
959
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
960
+
961
+ bool is_txhpb = reg->access->addr > A_TXFIFO_DATA2;
962
+
963
+ bool initiate_transfer = (reg->access->addr == A_TXFIFO_DATA2) ||
964
+ (reg->access->addr == A_TXHPB_DATA2);
965
+
966
+ Fifo32 *f = is_txhpb ? &s->txhpb_fifo : &s->tx_fifo;
967
+
968
+ if (!fifo32_is_full(f)) {
969
+ fifo32_push(f, val);
970
+ } else {
971
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
972
+
973
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: TX FIFO is full.\n", path);
974
+ }
975
+
976
+ /* Initiate the message send if TX register is written. */
977
+ if (initiate_transfer &&
978
+ ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
979
+ transfer_fifo(s, f);
980
+ }
981
+
982
+ can_update_irq(s);
983
+}
984
+
985
+static const RegisterAccessInfo can_regs_info[] = {
986
+ { .name = "SOFTWARE_RESET_REGISTER",
987
+ .addr = A_SOFTWARE_RESET_REGISTER,
988
+ .rsvd = 0xfffffffc,
989
+ .pre_write = can_srr_pre_write,
990
+ },{ .name = "MODE_SELECT_REGISTER",
991
+ .addr = A_MODE_SELECT_REGISTER,
992
+ .rsvd = 0xfffffff8,
993
+ .pre_write = can_msr_pre_write,
994
+ },{ .name = "ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER",
995
+ .addr = A_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER,
996
+ .rsvd = 0xffffff00,
997
+ .pre_write = can_brpr_pre_write,
998
+ },{ .name = "ARBITRATION_PHASE_BIT_TIMING_REGISTER",
999
+ .addr = A_ARBITRATION_PHASE_BIT_TIMING_REGISTER,
1000
+ .rsvd = 0xfffffe00,
1001
+ .pre_write = can_btr_pre_write,
1002
+ },{ .name = "ERROR_COUNTER_REGISTER",
1003
+ .addr = A_ERROR_COUNTER_REGISTER,
1004
+ .rsvd = 0xffff0000,
1005
+ .ro = 0xffffffff,
1006
+ },{ .name = "ERROR_STATUS_REGISTER",
1007
+ .addr = A_ERROR_STATUS_REGISTER,
1008
+ .rsvd = 0xffffffe0,
1009
+ .w1c = 0x1f,
1010
+ },{ .name = "STATUS_REGISTER", .addr = A_STATUS_REGISTER,
1011
+ .reset = 0x1,
1012
+ .rsvd = 0xffffe000,
1013
+ .ro = 0x1fff,
1014
+ },{ .name = "INTERRUPT_STATUS_REGISTER",
1015
+ .addr = A_INTERRUPT_STATUS_REGISTER,
1016
+ .reset = 0x6000,
1017
+ .rsvd = 0xffff8000,
1018
+ .ro = 0x7fff,
1019
+ },{ .name = "INTERRUPT_ENABLE_REGISTER",
1020
+ .addr = A_INTERRUPT_ENABLE_REGISTER,
1021
+ .rsvd = 0xffff8000,
1022
+ .post_write = can_ier_post_write,
1023
+ },{ .name = "INTERRUPT_CLEAR_REGISTER",
1024
+ .addr = A_INTERRUPT_CLEAR_REGISTER,
1025
+ .rsvd = 0xffff8000,
1026
+ .pre_write = can_icr_pre_write,
1027
+ },{ .name = "TIMESTAMP_REGISTER",
1028
+ .addr = A_TIMESTAMP_REGISTER,
1029
+ .rsvd = 0xfffffffe,
1030
+ .pre_write = can_tcr_pre_write,
1031
+ },{ .name = "WIR", .addr = A_WIR,
1032
+ .reset = 0x3f3f,
1033
+ .rsvd = 0xffff0000,
1034
+ },{ .name = "TXFIFO_ID", .addr = A_TXFIFO_ID,
1035
+ .post_write = can_tx_post_write,
1036
+ },{ .name = "TXFIFO_DLC", .addr = A_TXFIFO_DLC,
1037
+ .rsvd = 0xfffffff,
1038
+ .post_write = can_tx_post_write,
1039
+ },{ .name = "TXFIFO_DATA1", .addr = A_TXFIFO_DATA1,
1040
+ .post_write = can_tx_post_write,
1041
+ },{ .name = "TXFIFO_DATA2", .addr = A_TXFIFO_DATA2,
1042
+ .post_write = can_tx_post_write,
1043
+ },{ .name = "TXHPB_ID", .addr = A_TXHPB_ID,
1044
+ .post_write = can_tx_post_write,
1045
+ },{ .name = "TXHPB_DLC", .addr = A_TXHPB_DLC,
1046
+ .rsvd = 0xfffffff,
1047
+ .post_write = can_tx_post_write,
1048
+ },{ .name = "TXHPB_DATA1", .addr = A_TXHPB_DATA1,
1049
+ .post_write = can_tx_post_write,
1050
+ },{ .name = "TXHPB_DATA2", .addr = A_TXHPB_DATA2,
1051
+ .post_write = can_tx_post_write,
1052
+ },{ .name = "RXFIFO_ID", .addr = A_RXFIFO_ID,
1053
+ .ro = 0xffffffff,
1054
+ .post_read = can_rxfifo_pre_read,
1055
+ },{ .name = "RXFIFO_DLC", .addr = A_RXFIFO_DLC,
1056
+ .rsvd = 0xfff0000,
1057
+ .post_read = can_rxfifo_pre_read,
1058
+ },{ .name = "RXFIFO_DATA1", .addr = A_RXFIFO_DATA1,
1059
+ .post_read = can_rxfifo_pre_read,
1060
+ },{ .name = "RXFIFO_DATA2", .addr = A_RXFIFO_DATA2,
1061
+ .post_read = can_rxfifo_pre_read,
1062
+ },{ .name = "AFR", .addr = A_AFR,
1063
+ .rsvd = 0xfffffff0,
1064
+ .post_write = can_filter_enable_post_write,
1065
+ },{ .name = "AFMR1", .addr = A_AFMR1,
1066
+ .pre_write = can_filter_mask_pre_write,
1067
+ },{ .name = "AFIR1", .addr = A_AFIR1,
1068
+ .pre_write = can_filter_id_pre_write,
1069
+ },{ .name = "AFMR2", .addr = A_AFMR2,
1070
+ .pre_write = can_filter_mask_pre_write,
1071
+ },{ .name = "AFIR2", .addr = A_AFIR2,
1072
+ .pre_write = can_filter_id_pre_write,
1073
+ },{ .name = "AFMR3", .addr = A_AFMR3,
1074
+ .pre_write = can_filter_mask_pre_write,
1075
+ },{ .name = "AFIR3", .addr = A_AFIR3,
1076
+ .pre_write = can_filter_id_pre_write,
1077
+ },{ .name = "AFMR4", .addr = A_AFMR4,
1078
+ .pre_write = can_filter_mask_pre_write,
1079
+ },{ .name = "AFIR4", .addr = A_AFIR4,
1080
+ .pre_write = can_filter_id_pre_write,
1081
+ }
1082
+};
1083
+
1084
+static void xlnx_zynqmp_can_ptimer_cb(void *opaque)
1085
+{
1086
+ /* No action required on the timer rollover. */
1087
+}
1088
+
1089
+static const MemoryRegionOps can_ops = {
1090
+ .read = register_read_memory,
277
+ .read = register_read_memory,
1091
+ .write = register_write_memory,
278
+ .write = register_write_memory,
1092
+ .endianness = DEVICE_LITTLE_ENDIAN,
279
+ .endianness = DEVICE_LITTLE_ENDIAN,
1093
+ .valid = {
280
+ .valid = {
1094
+ .min_access_size = 4,
281
+ .min_access_size = 4,
1095
+ .max_access_size = 4,
282
+ .max_access_size = 4,
1096
+ },
283
+ },
1097
+};
284
+};
1098
+
285
+
1099
+static void xlnx_zynqmp_can_reset_init(Object *obj, ResetType type)
286
+static void xram_ctrl_realize(DeviceState *dev, Error **errp)
1100
+{
287
+{
1101
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
288
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
1102
+ unsigned int i;
289
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(dev);
1103
+
290
+
1104
+ for (i = R_RXFIFO_ID; i < ARRAY_SIZE(s->reg_info); ++i) {
291
+ switch (s->cfg.size) {
1105
+ register_reset(&s->reg_info[i]);
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;
1106
+ }
310
+ }
1107
+
311
+
1108
+ ptimer_transaction_begin(s->can_timer);
312
+ memory_region_init_ram(&s->ram, OBJECT(s),
1109
+ ptimer_set_count(s->can_timer, 0);
313
+ object_get_canonical_path_component(OBJECT(s)),
1110
+ ptimer_transaction_commit(s->can_timer);
314
+ s->cfg.size, &error_fatal);
1111
+}
315
+ sysbus_init_mmio(sbd, &s->ram);
1112
+
316
+}
1113
+static void xlnx_zynqmp_can_reset_hold(Object *obj)
317
+
1114
+{
318
+static void xram_ctrl_init(Object *obj)
1115
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
319
+{
1116
+ unsigned int i;
320
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
1117
+
1118
+ for (i = 0; i < R_RXFIFO_ID; ++i) {
1119
+ register_reset(&s->reg_info[i]);
1120
+ }
1121
+
1122
+ /*
1123
+ * Reset FIFOs when CAN model is reset. This will clear the fifo writes
1124
+ * done by post_write which gets called from register_reset function,
1125
+ * post_write handle will not be able to trigger tx because CAN will be
1126
+ * disabled when software_reset_register is cleared first.
1127
+ */
1128
+ fifo32_reset(&s->rx_fifo);
1129
+ fifo32_reset(&s->tx_fifo);
1130
+ fifo32_reset(&s->txhpb_fifo);
1131
+}
1132
+
1133
+static bool xlnx_zynqmp_can_can_receive(CanBusClientState *client)
1134
+{
1135
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1136
+ bus_client);
1137
+
1138
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
1139
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1140
+
1141
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is in reset state.\n",
1142
+ path);
1143
+ return false;
1144
+ }
1145
+
1146
+ if ((ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) == 0) {
1147
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1148
+
1149
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is disabled. Incoming"
1150
+ " messages will be discarded.\n", path);
1151
+ return false;
1152
+ }
1153
+
1154
+ return true;
1155
+}
1156
+
1157
+static ssize_t xlnx_zynqmp_can_receive(CanBusClientState *client,
1158
+ const qemu_can_frame *buf, size_t buf_size) {
1159
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1160
+ bus_client);
1161
+ const qemu_can_frame *frame = buf;
1162
+
1163
+ if (buf_size <= 0) {
1164
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1165
+
1166
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Error in the data received.\n",
1167
+ path);
1168
+ return 0;
1169
+ }
1170
+
1171
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
1172
+ /* Snoop Mode: Just keep the data. no response back. */
1173
+ update_rx_fifo(s, frame);
1174
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP))) {
1175
+ /*
1176
+ * XlnxZynqMPCAN is in sleep mode. Any data on bus will bring it to wake
1177
+ * up state.
1178
+ */
1179
+ can_exit_sleep_mode(s);
1180
+ update_rx_fifo(s, frame);
1181
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) == 0) {
1182
+ update_rx_fifo(s, frame);
1183
+ } else {
1184
+ /*
1185
+ * XlnxZynqMPCAN will not participate in normal bus communication
1186
+ * and will not receive any messages transmitted by other CAN nodes.
1187
+ */
1188
+ trace_xlnx_can_rx_discard(s->regs[R_STATUS_REGISTER]);
1189
+ }
1190
+
1191
+ return 1;
1192
+}
1193
+
1194
+static CanBusClientInfo can_xilinx_bus_client_info = {
1195
+ .can_receive = xlnx_zynqmp_can_can_receive,
1196
+ .receive = xlnx_zynqmp_can_receive,
1197
+};
1198
+
1199
+static int xlnx_zynqmp_can_connect_to_bus(XlnxZynqMPCANState *s,
1200
+ CanBusState *bus)
1201
+{
1202
+ s->bus_client.info = &can_xilinx_bus_client_info;
1203
+
1204
+ if (can_bus_insert_client(bus, &s->bus_client) < 0) {
1205
+ return -1;
1206
+ }
1207
+ return 0;
1208
+}
1209
+
1210
+static void xlnx_zynqmp_can_realize(DeviceState *dev, Error **errp)
1211
+{
1212
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(dev);
1213
+
1214
+ if (s->canbus) {
1215
+ if (xlnx_zynqmp_can_connect_to_bus(s, s->canbus) < 0) {
1216
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1217
+
1218
+ error_setg(errp, "%s: xlnx_zynqmp_can_connect_to_bus"
1219
+ " failed.", path);
1220
+ return;
1221
+ }
1222
+ }
1223
+
1224
+ /* Create RX FIFO, TXFIFO, TXHPB storage. */
1225
+ fifo32_create(&s->rx_fifo, RXFIFO_SIZE);
1226
+ fifo32_create(&s->tx_fifo, RXFIFO_SIZE);
1227
+ fifo32_create(&s->txhpb_fifo, CAN_FRAME_SIZE);
1228
+
1229
+ /* Allocate a new timer. */
1230
+ s->can_timer = ptimer_init(xlnx_zynqmp_can_ptimer_cb, s,
1231
+ PTIMER_POLICY_DEFAULT);
1232
+
1233
+ ptimer_transaction_begin(s->can_timer);
1234
+
1235
+ ptimer_set_freq(s->can_timer, s->cfg.ext_clk_freq);
1236
+ ptimer_set_limit(s->can_timer, CAN_TIMER_MAX, 1);
1237
+ ptimer_run(s->can_timer, 0);
1238
+ ptimer_transaction_commit(s->can_timer);
1239
+}
1240
+
1241
+static void xlnx_zynqmp_can_init(Object *obj)
1242
+{
1243
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1244
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
321
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1245
+
322
+
1246
+ RegisterInfoArray *reg_array;
323
+ s->reg_array =
1247
+
324
+ register_init_block32(DEVICE(obj), xram_ctrl_regs_info,
1248
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_CAN,
325
+ ARRAY_SIZE(xram_ctrl_regs_info),
1249
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
326
+ s->regs_info, s->regs,
1250
+ reg_array = register_init_block32(DEVICE(obj), can_regs_info,
327
+ &xram_ctrl_ops,
1251
+ ARRAY_SIZE(can_regs_info),
328
+ XLNX_XRAM_CTRL_ERR_DEBUG,
1252
+ s->reg_info, s->regs,
329
+ XRAM_CTRL_R_MAX * 4);
1253
+ &can_ops,
330
+ sysbus_init_mmio(sbd, &s->reg_array->mem);
1254
+ XLNX_ZYNQMP_CAN_ERR_DEBUG,
331
+ sysbus_init_irq(sbd, &s->irq);
1255
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
332
+}
1256
+
333
+
1257
+ memory_region_add_subregion(&s->iomem, 0x00, &reg_array->mem);
334
+static void xram_ctrl_finalize(Object *obj)
1258
+ sysbus_init_mmio(sbd, &s->iomem);
335
+{
1259
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
336
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
1260
+}
337
+ register_finalize_block(s->reg_array);
1261
+
338
+}
1262
+static const VMStateDescription vmstate_can = {
339
+
1263
+ .name = TYPE_XLNX_ZYNQMP_CAN,
340
+static const VMStateDescription vmstate_xram_ctrl = {
341
+ .name = TYPE_XLNX_XRAM_CTRL,
1264
+ .version_id = 1,
342
+ .version_id = 1,
1265
+ .minimum_version_id = 1,
343
+ .minimum_version_id = 1,
1266
+ .fields = (VMStateField[]) {
344
+ .fields = (VMStateField[]) {
1267
+ VMSTATE_FIFO32(rx_fifo, XlnxZynqMPCANState),
345
+ VMSTATE_UINT32_ARRAY(regs, XlnxXramCtrl, XRAM_CTRL_R_MAX),
1268
+ VMSTATE_FIFO32(tx_fifo, XlnxZynqMPCANState),
1269
+ VMSTATE_FIFO32(txhpb_fifo, XlnxZynqMPCANState),
1270
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPCANState, XLNX_ZYNQMP_CAN_R_MAX),
1271
+ VMSTATE_PTIMER(can_timer, XlnxZynqMPCANState),
1272
+ VMSTATE_END_OF_LIST(),
346
+ VMSTATE_END_OF_LIST(),
1273
+ }
347
+ }
1274
+};
348
+};
1275
+
349
+
1276
+static Property xlnx_zynqmp_can_properties[] = {
350
+static Property xram_ctrl_properties[] = {
1277
+ DEFINE_PROP_UINT32("ext_clk_freq", XlnxZynqMPCANState, cfg.ext_clk_freq,
351
+ DEFINE_PROP_UINT64("size", XlnxXramCtrl, cfg.size, 1 * MiB),
1278
+ CAN_DEFAULT_CLOCK),
1279
+ DEFINE_PROP_LINK("canbus", XlnxZynqMPCANState, canbus, TYPE_CAN_BUS,
1280
+ CanBusState *),
1281
+ DEFINE_PROP_END_OF_LIST(),
352
+ DEFINE_PROP_END_OF_LIST(),
1282
+};
353
+};
1283
+
354
+
1284
+static void xlnx_zynqmp_can_class_init(ObjectClass *klass, void *data)
355
+static void xram_ctrl_class_init(ObjectClass *klass, void *data)
1285
+{
356
+{
357
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
1286
+ DeviceClass *dc = DEVICE_CLASS(klass);
358
+ DeviceClass *dc = DEVICE_CLASS(klass);
1287
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
359
+
1288
+
360
+ dc->realize = xram_ctrl_realize;
1289
+ rc->phases.enter = xlnx_zynqmp_can_reset_init;
361
+ dc->vmsd = &vmstate_xram_ctrl;
1290
+ rc->phases.hold = xlnx_zynqmp_can_reset_hold;
362
+ device_class_set_props(dc, xram_ctrl_properties);
1291
+ dc->realize = xlnx_zynqmp_can_realize;
363
+
1292
+ device_class_set_props(dc, xlnx_zynqmp_can_properties);
364
+ rc->phases.enter = xram_ctrl_reset_enter;
1293
+ dc->vmsd = &vmstate_can;
365
+ rc->phases.hold = xram_ctrl_reset_hold;
1294
+}
366
+}
1295
+
367
+
1296
+static const TypeInfo can_info = {
368
+static const TypeInfo xram_ctrl_info = {
1297
+ .name = TYPE_XLNX_ZYNQMP_CAN,
369
+ .name = TYPE_XLNX_XRAM_CTRL,
1298
+ .parent = TYPE_SYS_BUS_DEVICE,
370
+ .parent = TYPE_SYS_BUS_DEVICE,
1299
+ .instance_size = sizeof(XlnxZynqMPCANState),
371
+ .instance_size = sizeof(XlnxXramCtrl),
1300
+ .class_init = xlnx_zynqmp_can_class_init,
372
+ .class_init = xram_ctrl_class_init,
1301
+ .instance_init = xlnx_zynqmp_can_init,
373
+ .instance_init = xram_ctrl_init,
1302
+};
374
+ .instance_finalize = xram_ctrl_finalize,
1303
+
375
+};
1304
+static void can_register_types(void)
376
+
1305
+{
377
+static void xram_ctrl_register_types(void)
1306
+ type_register_static(&can_info);
378
+{
1307
+}
379
+ type_register_static(&xram_ctrl_info);
1308
+
380
+}
1309
+type_init(can_register_types)
381
+
1310
diff --git a/hw/Kconfig b/hw/Kconfig
382
+type_init(xram_ctrl_register_types)
383
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
1311
index XXXXXXX..XXXXXXX 100644
384
index XXXXXXX..XXXXXXX 100644
1312
--- a/hw/Kconfig
385
--- a/hw/misc/meson.build
1313
+++ b/hw/Kconfig
386
+++ b/hw/misc/meson.build
1314
@@ -XXX,XX +XXX,XX @@ config XILINX_AXI
387
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files(
1315
config XLNX_ZYNQMP
388
))
1316
bool
389
softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c'))
1317
select REGISTER
390
softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c', 'zynq-xadc.c'))
1318
+ select CAN_BUS
391
+softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-xramc.c'))
1319
diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
392
softmmu_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c'))
1320
index XXXXXXX..XXXXXXX 100644
393
softmmu_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c'))
1321
--- a/hw/net/can/meson.build
394
softmmu_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c'))
1322
+++ b/hw/net/can/meson.build
1323
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_pcm3680_pci.c'))
1324
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_mioe3680_pci.c'))
1325
softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD', if_true: files('ctucan_core.c'))
1326
softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD_PCI', if_true: files('ctucan_pci.c'))
1327
+softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
1328
diff --git a/hw/net/can/trace-events b/hw/net/can/trace-events
1329
new file mode 100644
1330
index XXXXXXX..XXXXXXX
1331
--- /dev/null
1332
+++ b/hw/net/can/trace-events
1333
@@ -XXX,XX +XXX,XX @@
1334
+# xlnx-zynqmp-can.c
1335
+xlnx_can_update_irq(uint32_t isr, uint32_t ier, uint32_t irq) "ISR: 0x%08x IER: 0x%08x IRQ: 0x%08x"
1336
+xlnx_can_reset(uint32_t val) "Resetting controller with value = 0x%08x"
1337
+xlnx_can_rx_fifo_filter_reject(uint32_t id, uint8_t dlc) "Frame: ID: 0x%08x DLC: 0x%02x"
1338
+xlnx_can_filter_id_pre_write(uint8_t filter_num, uint32_t value) "Filter%d ID: 0x%08x"
1339
+xlnx_can_filter_mask_pre_write(uint8_t filter_num, uint32_t value) "Filter%d MASK: 0x%08x"
1340
+xlnx_can_tx_data(uint32_t id, uint8_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
1341
+xlnx_can_rx_data(uint32_t id, uint32_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
1342
+xlnx_can_rx_discard(uint32_t status) "Controller is not enabled for bus communication. Status Register: 0x%08x"
1343
--
395
--
1344
2.20.1
396
2.20.1
1345
397
1346
398
diff view generated by jsdifflib
1
Factor out the code which handles M-profile lazy FP state preservation
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
from full_vfp_access_check(); accesses to the FPCXT_NS register are
3
a special case which need to do just this part (corresponding in the
4
pseudocode to the PreserveFPState() function), and not the full
5
set of actions matching the pseudocode ExecuteFPCheck() which
6
normal FP instructions need to do.
7
2
3
Connect the support for the Versal Accelerator RAMs (XRAMs).
4
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
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20201119215617.29887-13-peter.maydell@linaro.org
12
---
10
---
13
target/arm/translate-vfp.c.inc | 45 ++++++++++++++++++++--------------
11
docs/system/arm/xlnx-versal-virt.rst | 1 +
14
1 file changed, 27 insertions(+), 18 deletions(-)
12
include/hw/arm/xlnx-versal.h | 13 ++++++++++
13
hw/arm/xlnx-versal.c | 36 ++++++++++++++++++++++++++++
14
3 files changed, 50 insertions(+)
15
15
16
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
16
diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate-vfp.c.inc
18
--- a/docs/system/arm/xlnx-versal-virt.rst
19
+++ b/target/arm/translate-vfp.c.inc
19
+++ b/docs/system/arm/xlnx-versal-virt.rst
20
@@ -XXX,XX +XXX,XX @@ static inline long vfp_f16_offset(unsigned reg, bool top)
20
@@ -XXX,XX +XXX,XX @@ Implemented devices:
21
return offs;
21
- 8 ADMA (Xilinx zDMA) channels
22
- 2 SD Controllers
23
- OCM (256KB of On Chip Memory)
24
+- XRAM (4MB of on chip Accelerator RAM)
25
- DDR memory
26
27
QEMU does not yet model any other devices, including the PL and the AI Engine.
28
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/arm/xlnx-versal.h
31
+++ b/include/hw/arm/xlnx-versal.h
32
@@ -XXX,XX +XXX,XX @@
33
34
#include "hw/sysbus.h"
35
#include "hw/arm/boot.h"
36
+#include "hw/or-irq.h"
37
#include "hw/sd/sdhci.h"
38
#include "hw/intc/arm_gicv3.h"
39
#include "hw/char/pl011.h"
40
@@ -XXX,XX +XXX,XX @@
41
#include "hw/rtc/xlnx-zynqmp-rtc.h"
42
#include "qom/object.h"
43
#include "hw/usb/xlnx-usb-subsystem.h"
44
+#include "hw/misc/xlnx-versal-xramc.h"
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
88
index XXXXXXX..XXXXXXX 100644
89
--- a/hw/arm/xlnx-versal.c
90
+++ b/hw/arm/xlnx-versal.c
91
@@ -XXX,XX +XXX,XX @@
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]);
22
}
101
}
23
102
24
+/*
103
+static void versal_create_xrams(Versal *s, qemu_irq *pic)
25
+ * Generate code for M-profile lazy FP state preservation if needed;
26
+ * this corresponds to the pseudocode PreserveFPState() function.
27
+ */
28
+static void gen_preserve_fp_state(DisasContext *s)
29
+{
104
+{
30
+ if (s->v7m_lspact) {
105
+ int nr_xrams = ARRAY_SIZE(s->lpd.xram.ctrl);
31
+ /*
106
+ DeviceState *orgate;
32
+ * Lazy state saving affects external memory and also the NVIC,
107
+ int i;
33
+ * so we must mark it as an IO operation for icount (and cause
108
+
34
+ * this to be the last insn in the TB).
109
+ /* XRAM IRQs get ORed into a single line. */
35
+ */
110
+ object_initialize_child(OBJECT(s), "xram-irq-orgate",
36
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
111
+ &s->lpd.xram.irq_orgate, TYPE_OR_IRQ);
37
+ s->base.is_jmp = DISAS_UPDATE_EXIT;
112
+ orgate = DEVICE(&s->lpd.xram.irq_orgate);
38
+ gen_io_start();
113
+ object_property_set_int(OBJECT(orgate),
39
+ }
114
+ "num-lines", nr_xrams, &error_fatal);
40
+ gen_helper_v7m_preserve_fp_state(cpu_env);
115
+ qdev_realize(orgate, NULL, &error_fatal);
41
+ /*
116
+ qdev_connect_gpio_out(orgate, 0, pic[VERSAL_XRAM_IRQ_0]);
42
+ * If the preserve_fp_state helper doesn't throw an exception
117
+
43
+ * then it will clear LSPACT; we don't need to repeat this for
118
+ for (i = 0; i < ARRAY_SIZE(s->lpd.xram.ctrl); i++) {
44
+ * any further FP insns in this TB.
119
+ SysBusDevice *sbd;
45
+ */
120
+ MemoryRegion *mr;
46
+ s->v7m_lspact = false;
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));
47
+ }
134
+ }
48
+}
135
+}
49
+
136
+
50
/*
137
/* This takes the board allocated linear DDR memory and creates aliases
51
* Check that VFP access is enabled. If it is, do the necessary
138
* for each split DDR range/aperture on the Versal address map.
52
* M-profile lazy-FP handling and then return true.
139
*/
53
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
140
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
54
/* Handle M-profile lazy FP state mechanics */
141
versal_create_admas(s, pic);
55
142
versal_create_sds(s, pic);
56
/* Trigger lazy-state preservation if necessary */
143
versal_create_rtc(s, pic);
57
- if (s->v7m_lspact) {
144
+ versal_create_xrams(s, pic);
58
- /*
145
versal_map_ddr(s);
59
- * Lazy state saving affects external memory and also the NVIC,
146
versal_unimp(s);
60
- * so we must mark it as an IO operation for icount (and cause
147
61
- * this to be the last insn in the TB).
62
- */
63
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
64
- s->base.is_jmp = DISAS_UPDATE_EXIT;
65
- gen_io_start();
66
- }
67
- gen_helper_v7m_preserve_fp_state(cpu_env);
68
- /*
69
- * If the preserve_fp_state helper doesn't throw an exception
70
- * then it will clear LSPACT; we don't need to repeat this for
71
- * any further FP insns in this TB.
72
- */
73
- s->v7m_lspact = false;
74
- }
75
+ gen_preserve_fp_state(s);
76
77
/* Update ownership of FP context: set FPCCR.S to match current state */
78
if (s->v8m_fpccr_s_wrong) {
79
--
148
--
80
2.20.1
149
2.20.1
81
150
82
151
diff view generated by jsdifflib
New patch
1
From: Eric Auger <eric.auger@redhat.com>
1
2
3
With -Werror=maybe-uninitialized configuration we get
4
../hw/i386/intel_iommu.c: In function ‘vtd_context_device_invalidate’:
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
| ~~~~~^~~~~~~
9
10
Add a g_assert_not_reached() to avoid the error.
11
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
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
hw/i386/intel_iommu.c | 2 ++
19
1 file changed, 2 insertions(+)
20
21
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/i386/intel_iommu.c
24
+++ b/hw/i386/intel_iommu.c
25
@@ -XXX,XX +XXX,XX @@ static void vtd_context_device_invalidate(IntelIOMMUState *s,
26
case 3:
27
mask = 7; /* Mask bit 2:0 in the SID field */
28
break;
29
+ default:
30
+ g_assert_not_reached();
31
}
32
mask = ~mask;
33
34
--
35
2.20.1
36
37
diff view generated by jsdifflib
1
Currently M-profile borrows the A-profile code for VMSR and VMRS
1
From: Eric Auger <eric.auger@redhat.com>
2
(access to the FP system registers), because all it needs to support
3
is the FPSCR. In v8.1M things become significantly more complicated
4
in two ways:
5
2
6
* there are several new FP system registers; some have side effects
3
Currently get_naturally_aligned_size() is used by the intel iommu
7
on read, and one (FPCXT_NS) needs to avoid the usual
4
to compute the maximum invalidation range based on @size which is
8
vfp_access_check() and the "only if FPU implemented" check
5
a power of 2 while being aligned with the @start address and less
6
than the maximum range defined by @gaw.
9
7
10
* all sysregs are now accessible both by VMRS/VMSR (which
8
This helper is also useful for other iommu devices (virtio-iommu,
11
reads/writes a general purpose register) and also by VLDR/VSTR
9
SMMUv3) to make sure IOMMU UNMAP notifiers only are called with
12
(which reads/writes them directly to memory)
10
power of 2 range sizes.
13
11
14
Refactor the structure of how we handle VMSR/VMRS to cope with this:
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.
15
16
16
* keep the M-profile code entirely separate from the A-profile code
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
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
include/sysemu/dma.h | 12 ++++++++++++
23
hw/i386/intel_iommu.c | 30 +++++++-----------------------
24
softmmu/dma-helpers.c | 26 ++++++++++++++++++++++++++
25
3 files changed, 45 insertions(+), 23 deletions(-)
17
26
18
* abstract out the "read or write the general purpose register" part
27
diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
19
of the code into a loadfn or storefn function pointer, so we can
20
reuse it for VLDR/VSTR.
21
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 20201119215617.29887-8-peter.maydell@linaro.org
25
---
26
target/arm/cpu.h | 3 +
27
target/arm/translate-vfp.c.inc | 182 ++++++++++++++++++++++++++++++---
28
2 files changed, 171 insertions(+), 14 deletions(-)
29
30
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
31
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.h
29
--- a/include/sysemu/dma.h
33
+++ b/target/arm/cpu.h
30
+++ b/include/sysemu/dma.h
34
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
31
@@ -XXX,XX +XXX,XX @@ uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg);
35
#define ARM_VFP_FPINST 9
32
void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
36
#define ARM_VFP_FPINST2 10
33
QEMUSGList *sg, enum BlockAcctType type);
37
34
38
+/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
35
+/**
39
+#define QEMU_VFP_FPSCR_NZCV 0xffff
36
+ * dma_aligned_pow2_mask: Return the address bit mask of the largest
37
+ * power of 2 size less or equal than @end - @start + 1, aligned with @start,
38
+ * and bounded by 1 << @max_addr_bits bits.
39
+ *
40
+ * @start: range start address
41
+ * @end: range end address (greater than @start)
42
+ * @max_addr_bits: max address bits (<= 64)
43
+ */
44
+uint64_t dma_aligned_pow2_mask(uint64_t start, uint64_t end,
45
+ int max_addr_bits);
40
+
46
+
41
/* iwMMXt coprocessor control registers. */
47
#endif
42
#define ARM_IWMMXT_wCID 0
48
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
43
#define ARM_IWMMXT_wCon 1
44
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
45
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/translate-vfp.c.inc
50
--- a/hw/i386/intel_iommu.c
47
+++ b/target/arm/translate-vfp.c.inc
51
+++ b/hw/i386/intel_iommu.c
48
@@ -XXX,XX +XXX,XX @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
52
@@ -XXX,XX +XXX,XX @@
49
return true;
53
#include "hw/i386/x86-iommu.h"
54
#include "hw/pci-host/q35.h"
55
#include "sysemu/kvm.h"
56
+#include "sysemu/dma.h"
57
#include "sysemu/sysemu.h"
58
#include "hw/i386/apic_internal.h"
59
#include "kvm/kvm_i386.h"
60
@@ -XXX,XX +XXX,XX @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
61
return vtd_dev_as;
50
}
62
}
51
63
52
+/*
64
-static uint64_t get_naturally_aligned_size(uint64_t start,
53
+ * M-profile provides two different sets of instructions that can
65
- uint64_t size, int gaw)
54
+ * access floating point system registers: VMSR/VMRS (which move
66
-{
55
+ * to/from a general purpose register) and VLDR/VSTR sysreg (which
67
- uint64_t max_mask = 1ULL << gaw;
56
+ * move directly to/from memory). In some cases there are also side
68
- uint64_t alignment = start ? start & -start : max_mask;
57
+ * effects which must happen after any write to memory (which could
69
-
58
+ * cause an exception). So we implement the common logic for the
70
- alignment = MIN(alignment, max_mask);
59
+ * sysreg access in gen_M_fp_sysreg_write() and gen_M_fp_sysreg_read(),
71
- size = MIN(size, max_mask);
60
+ * which take pointers to callback functions which will perform the
72
-
61
+ * actual "read/write general purpose register" and "read/write
73
- if (alignment <= size) {
62
+ * memory" operations.
74
- /* Increase the alignment of start */
63
+ */
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
}
64
+
122
+
65
+/*
123
+uint64_t dma_aligned_pow2_mask(uint64_t start, uint64_t end, int max_addr_bits)
66
+ * Emit code to store the sysreg to its final destination; frees the
124
+{
67
+ * TCG temp 'value' it is passed.
125
+ uint64_t max_mask = UINT64_MAX, addr_mask = end - start;
68
+ */
126
+ uint64_t alignment_mask, size_mask;
69
+typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
70
+/*
71
+ * Emit code to load the value to be copied to the sysreg; returns
72
+ * a new TCG temporary
73
+ */
74
+typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
75
+
127
+
76
+/* Common decode/access checks for fp sysreg read/write */
128
+ if (max_addr_bits != 64) {
77
+typedef enum FPSysRegCheckResult {
129
+ max_mask = (1ULL << max_addr_bits) - 1;
78
+ FPSysRegCheckFailed, /* caller should return false */
79
+ FPSysRegCheckDone, /* caller should return true */
80
+ FPSysRegCheckContinue, /* caller should continue generating code */
81
+} FPSysRegCheckResult;
82
+
83
+static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
84
+{
85
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
86
+ return FPSysRegCheckFailed;
87
+ }
130
+ }
88
+
131
+
89
+ switch (regno) {
132
+ alignment_mask = start ? (start & -start) - 1 : max_mask;
90
+ case ARM_VFP_FPSCR:
133
+ alignment_mask = MIN(alignment_mask, max_mask);
91
+ case QEMU_VFP_FPSCR_NZCV:
134
+ size_mask = MIN(addr_mask, max_mask);
92
+ break;
93
+ default:
94
+ return FPSysRegCheckFailed;
95
+ }
96
+
135
+
97
+ if (!vfp_access_check(s)) {
136
+ if (alignment_mask <= size_mask) {
98
+ return FPSysRegCheckDone;
137
+ /* Increase the alignment of start */
99
+ }
138
+ return alignment_mask;
100
+
101
+ return FPSysRegCheckContinue;
102
+}
103
+
104
+static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
105
+
106
+ fp_sysreg_loadfn *loadfn,
107
+ void *opaque)
108
+{
109
+ /* Do a write to an M-profile floating point system register */
110
+ TCGv_i32 tmp;
111
+
112
+ switch (fp_sysreg_checks(s, regno)) {
113
+ case FPSysRegCheckFailed:
114
+ return false;
115
+ case FPSysRegCheckDone:
116
+ return true;
117
+ case FPSysRegCheckContinue:
118
+ break;
119
+ }
120
+
121
+ switch (regno) {
122
+ case ARM_VFP_FPSCR:
123
+ tmp = loadfn(s, opaque);
124
+ gen_helper_vfp_set_fpscr(cpu_env, tmp);
125
+ tcg_temp_free_i32(tmp);
126
+ gen_lookup_tb(s);
127
+ break;
128
+ default:
129
+ g_assert_not_reached();
130
+ }
131
+ return true;
132
+}
133
+
134
+static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
135
+ fp_sysreg_storefn *storefn,
136
+ void *opaque)
137
+{
138
+ /* Do a read from an M-profile floating point system register */
139
+ TCGv_i32 tmp;
140
+
141
+ switch (fp_sysreg_checks(s, regno)) {
142
+ case FPSysRegCheckFailed:
143
+ return false;
144
+ case FPSysRegCheckDone:
145
+ return true;
146
+ case FPSysRegCheckContinue:
147
+ break;
148
+ }
149
+
150
+ switch (regno) {
151
+ case ARM_VFP_FPSCR:
152
+ tmp = tcg_temp_new_i32();
153
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
154
+ storefn(s, opaque, tmp);
155
+ break;
156
+ case QEMU_VFP_FPSCR_NZCV:
157
+ /*
158
+ * Read just NZCV; this is a special case to avoid the
159
+ * helper call for the "VMRS to CPSR.NZCV" insn.
160
+ */
161
+ tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
162
+ tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
163
+ storefn(s, opaque, tmp);
164
+ break;
165
+ default:
166
+ g_assert_not_reached();
167
+ }
168
+ return true;
169
+}
170
+
171
+static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
172
+{
173
+ arg_VMSR_VMRS *a = opaque;
174
+
175
+ if (a->rt == 15) {
176
+ /* Set the 4 flag bits in the CPSR */
177
+ gen_set_nzcv(value);
178
+ tcg_temp_free_i32(value);
179
+ } else {
139
+ } else {
180
+ store_reg(s, a->rt, value);
140
+ /* Find the largest page mask from size */
141
+ if (addr_mask == UINT64_MAX) {
142
+ return UINT64_MAX;
143
+ }
144
+ return (1ULL << (63 - clz64(addr_mask + 1))) - 1;
181
+ }
145
+ }
182
+}
146
+}
183
+
147
+
184
+static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
185
+{
186
+ arg_VMSR_VMRS *a = opaque;
187
+
188
+ return load_reg(s, a->rt);
189
+}
190
+
191
+static bool gen_M_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
192
+{
193
+ /*
194
+ * Accesses to R15 are UNPREDICTABLE; we choose to undef.
195
+ * FPSCR -> r15 is a special case which writes to the PSR flags;
196
+ * set a->reg to a special value to tell gen_M_fp_sysreg_read()
197
+ * we only care about the top 4 bits of FPSCR there.
198
+ */
199
+ if (a->rt == 15) {
200
+ if (a->l && a->reg == ARM_VFP_FPSCR) {
201
+ a->reg = QEMU_VFP_FPSCR_NZCV;
202
+ } else {
203
+ return false;
204
+ }
205
+ }
206
+
207
+ if (a->l) {
208
+ /* VMRS, move FP system register to gp register */
209
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_gpr, a);
210
+ } else {
211
+ /* VMSR, move gp register to FP system register */
212
+ return gen_M_fp_sysreg_write(s, a->reg, gpr_to_fp_sysreg, a);
213
+ }
214
+}
215
+
216
static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
217
{
218
TCGv_i32 tmp;
219
bool ignore_vfp_enabled = false;
220
221
- if (!dc_isar_feature(aa32_fpsp_v2, s)) {
222
- return false;
223
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
224
+ return gen_M_VMSR_VMRS(s, a);
225
}
226
227
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
228
- /*
229
- * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
230
- * Accesses to R15 are UNPREDICTABLE; we choose to undef.
231
- * (FPSCR -> r15 is a special case which writes to the PSR flags.)
232
- */
233
- if (a->reg != ARM_VFP_FPSCR) {
234
- return false;
235
- }
236
- if (a->rt == 15 && !a->l) {
237
- return false;
238
- }
239
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
240
+ return false;
241
}
242
243
switch (a->reg) {
244
--
148
--
245
2.20.1
149
2.20.1
246
150
247
151
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
Connect CAN0 and CAN1 on the ZynqMP.
3
Unmap notifiers work with an address mask assuming an
4
invalidation range of a power of 2. Nothing mandates this
5
in the VIRTIO-IOMMU spec.
4
6
5
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
7
So in case the range is not a power of 2, split it into
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
several invalidations.
7
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
9
8
Message-id: 1605728926-352690-3-git-send-email-fnu.vikram@xilinx.com
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
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
14
---
11
include/hw/arm/xlnx-zynqmp.h | 8 ++++++++
15
hw/virtio/virtio-iommu.c | 19 ++++++++++++++++---
12
hw/arm/xlnx-zcu102.c | 20 ++++++++++++++++++++
16
1 file changed, 16 insertions(+), 3 deletions(-)
13
hw/arm/xlnx-zynqmp.c | 34 ++++++++++++++++++++++++++++++++++
14
3 files changed, 62 insertions(+)
15
17
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
18
diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-zynqmp.h
20
--- a/hw/virtio/virtio-iommu.c
19
+++ b/include/hw/arm/xlnx-zynqmp.h
21
+++ b/hw/virtio/virtio-iommu.c
20
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start,
21
#include "hw/intc/arm_gic.h"
23
hwaddr virt_end)
22
#include "hw/net/cadence_gem.h"
24
{
23
#include "hw/char/cadence_uart.h"
25
IOMMUTLBEvent event;
24
+#include "hw/net/xlnx-zynqmp-can.h"
26
+ uint64_t delta = virt_end - virt_start;
25
#include "hw/ide/ahci.h"
27
26
#include "hw/sd/sdhci.h"
28
if (!(mr->iommu_notify_flags & IOMMU_NOTIFIER_UNMAP)) {
27
#include "hw/ssi/xilinx_spips.h"
29
return;
28
@@ -XXX,XX +XXX,XX @@
30
@@ -XXX,XX +XXX,XX @@ static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start,
29
#include "hw/cpu/cluster.h"
31
30
#include "target/arm/cpu.h"
32
event.type = IOMMU_NOTIFIER_UNMAP;
31
#include "qom/object.h"
33
event.entry.target_as = &address_space_memory;
32
+#include "net/can_emu.h"
34
- event.entry.addr_mask = virt_end - virt_start;
33
35
- event.entry.iova = virt_start;
34
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
36
event.entry.perm = IOMMU_NONE;
35
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
37
event.entry.translated_addr = 0;
36
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
38
+ event.entry.addr_mask = delta;
37
#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
39
+ event.entry.iova = virt_start;
38
#define XLNX_ZYNQMP_NUM_GEMS 4
40
39
#define XLNX_ZYNQMP_NUM_UARTS 2
41
- memory_region_notify_iommu(mr, 0, event);
40
+#define XLNX_ZYNQMP_NUM_CAN 2
42
+ if (delta == UINT64_MAX) {
41
+#define XLNX_ZYNQMP_CAN_REF_CLK (24 * 1000 * 1000)
43
+ memory_region_notify_iommu(mr, 0, event);
42
#define XLNX_ZYNQMP_NUM_SDHCI 2
43
#define XLNX_ZYNQMP_NUM_SPIS 2
44
#define XLNX_ZYNQMP_NUM_GDMA_CH 8
45
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
46
47
CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
48
CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
49
+ XlnxZynqMPCANState can[XLNX_ZYNQMP_NUM_CAN];
50
SysbusAHCIState sata;
51
SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
52
XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
53
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
54
bool virt;
55
/* Has the RPU subsystem? */
56
bool has_rpu;
57
+
58
+ /* CAN bus. */
59
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
60
};
61
62
#endif
63
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/arm/xlnx-zcu102.c
66
+++ b/hw/arm/xlnx-zcu102.c
67
@@ -XXX,XX +XXX,XX @@
68
#include "sysemu/qtest.h"
69
#include "sysemu/device_tree.h"
70
#include "qom/object.h"
71
+#include "net/can_emu.h"
72
73
struct XlnxZCU102 {
74
MachineState parent_obj;
75
@@ -XXX,XX +XXX,XX @@ struct XlnxZCU102 {
76
bool secure;
77
bool virt;
78
79
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
80
+
81
struct arm_boot_info binfo;
82
};
83
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
85
object_property_set_bool(OBJECT(&s->soc), "virtualization", s->virt,
86
&error_fatal);
87
88
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
89
+ gchar *bus_name = g_strdup_printf("canbus%d", i);
90
+
91
+ object_property_set_link(OBJECT(&s->soc), bus_name,
92
+ OBJECT(s->canbus[i]), &error_fatal);
93
+ g_free(bus_name);
94
+ }
44
+ }
95
+
45
+
96
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
97
98
/* Create and plug in the SD cards */
99
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
100
s->secure = false;
101
/* Default to virt (EL2) being disabled */
102
s->virt = false;
103
+ object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
104
+ (Object **)&s->canbus[0],
105
+ object_property_allow_set_link,
106
+ 0);
107
+
46
+
108
+ object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
47
+ while (virt_start != virt_end + 1) {
109
+ (Object **)&s->canbus[1],
48
+ uint64_t mask = dma_aligned_pow2_mask(virt_start, virt_end, 64);
110
+ object_property_allow_set_link,
49
+
111
+ 0);
50
+ event.entry.addr_mask = mask;
51
+ event.entry.iova = virt_start;
52
+ memory_region_notify_iommu(mr, 0, event);
53
+ virt_start += mask + 1;
54
+ }
112
}
55
}
113
56
114
static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
57
static gboolean virtio_iommu_notify_unmap_cb(gpointer key, gpointer value,
115
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/hw/arm/xlnx-zynqmp.c
118
+++ b/hw/arm/xlnx-zynqmp.c
119
@@ -XXX,XX +XXX,XX @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] = {
120
21, 22,
121
};
122
123
+static const uint64_t can_addr[XLNX_ZYNQMP_NUM_CAN] = {
124
+ 0xFF060000, 0xFF070000,
125
+};
126
+
127
+static const int can_intr[XLNX_ZYNQMP_NUM_CAN] = {
128
+ 23, 24,
129
+};
130
+
131
static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] = {
132
0xFF160000, 0xFF170000,
133
};
134
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
135
TYPE_CADENCE_UART);
136
}
137
138
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
139
+ object_initialize_child(obj, "can[*]", &s->can[i],
140
+ TYPE_XLNX_ZYNQMP_CAN);
141
+ }
142
+
143
object_initialize_child(obj, "sata", &s->sata, TYPE_SYSBUS_AHCI);
144
145
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
146
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
147
gic_spi[uart_intr[i]]);
148
}
149
150
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
151
+ object_property_set_int(OBJECT(&s->can[i]), "ext_clk_freq",
152
+ XLNX_ZYNQMP_CAN_REF_CLK, &error_abort);
153
+
154
+ object_property_set_link(OBJECT(&s->can[i]), "canbus",
155
+ OBJECT(s->canbus[i]), &error_fatal);
156
+
157
+ sysbus_realize(SYS_BUS_DEVICE(&s->can[i]), &err);
158
+ if (err) {
159
+ error_propagate(errp, err);
160
+ return;
161
+ }
162
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->can[i]), 0, can_addr[i]);
163
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->can[i]), 0,
164
+ gic_spi[can_intr[i]]);
165
+ }
166
+
167
object_property_set_int(OBJECT(&s->sata), "num-ports", SATA_NUM_PORTS,
168
&error_abort);
169
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sata), errp)) {
170
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
171
DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
172
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
173
MemoryRegion *),
174
+ DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
175
+ CanBusState *),
176
+ DEFINE_PROP_LINK("canbus1", XlnxZynqMPState, canbus[1], TYPE_CAN_BUS,
177
+ CanBusState *),
178
DEFINE_PROP_END_OF_LIST()
179
};
180
181
--
58
--
182
2.20.1
59
2.20.1
183
60
184
61
diff view generated by jsdifflib
New patch
1
From: Eric Auger <eric.auger@redhat.com>
1
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>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/arm/smmu-common.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/smmu-common.c
19
+++ b/hw/arm/smmu-common.c
20
@@ -XXX,XX +XXX,XX @@ inline void
21
smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
22
uint8_t tg, uint64_t num_pages, uint8_t ttl)
23
{
24
- if (ttl && (num_pages == 1)) {
25
+ if (ttl && (num_pages == 1) && (asid >= 0)) {
26
SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova, tg, ttl);
27
28
g_hash_table_remove(s->iotlb, &key);
29
--
30
2.20.1
31
32
diff view generated by jsdifflib
1
v8.1M adds new encodings of VLLDM and VLSTM (where bit 7 is set).
1
From: Eric Auger <eric.auger@redhat.com>
2
The only difference is that:
3
* the old T1 encodings UNDEF if the implementation implements 32
4
Dregs (this is currently architecturally impossible for M-profile)
5
* the new T2 encodings have the implementation-defined option to
6
read from memory (discarding the data) or write UNKNOWN values to
7
memory for the stack slots that would be D16-D31
8
2
9
We choose not to make those accesses, so for us the two
3
As of today, the driver can invalidate a number of pages that is
10
instructions behave identically assuming they don't UNDEF.
4
not a power of 2. However IOTLB unmap notifications and internal
5
IOTLB invalidations work with masks leading to erroneous
6
invalidations.
11
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>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20201119215617.29887-21-peter.maydell@linaro.org
15
---
20
---
16
target/arm/m-nocp.decode | 2 +-
21
hw/arm/smmu-common.c | 30 ++++++++++++++++++------------
17
target/arm/translate-vfp.c.inc | 25 +++++++++++++++++++++++++
22
hw/arm/smmuv3.c | 24 ++++++++++++++++++++----
18
2 files changed, 26 insertions(+), 1 deletion(-)
23
2 files changed, 38 insertions(+), 16 deletions(-)
19
24
20
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
25
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
21
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/m-nocp.decode
27
--- a/hw/arm/smmu-common.c
23
+++ b/target/arm/m-nocp.decode
28
+++ b/hw/arm/smmu-common.c
24
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@ inline void
25
30
smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
31
uint8_t tg, uint64_t num_pages, uint8_t ttl)
26
{
32
{
27
# Special cases which do not take an early NOCP: VLLDM and VLSTM
33
+ /* if tg is not set we use 4KB range invalidation */
28
- VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
34
+ uint8_t granule = tg ? tg * 2 + 10 : 12;
29
+ VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 op:1 000 0000
35
+
30
# VSCCLRM (new in v8.1M) is similar:
36
if (ttl && (num_pages == 1) && (asid >= 0)) {
31
VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
37
SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova, tg, ttl);
32
VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
38
33
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
39
- g_hash_table_remove(s->iotlb, &key);
34
index XXXXXXX..XXXXXXX 100644
40
- } else {
35
--- a/target/arm/translate-vfp.c.inc
41
- /* if tg is not set we use 4KB range invalidation */
36
+++ b/target/arm/translate-vfp.c.inc
42
- uint8_t granule = tg ? tg * 2 + 10 : 12;
37
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
43
-
38
!arm_dc_feature(s, ARM_FEATURE_V8)) {
44
- SMMUIOTLBPageInvInfo info = {
39
return false;
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
+ */
40
}
58
}
41
+
59
+
42
+ if (a->op) {
60
+ SMMUIOTLBPageInvInfo info = {
43
+ /*
61
+ .asid = asid, .iova = iova,
44
+ * T2 encoding ({D0-D31} reglist): v8.1M and up. We choose not
62
+ .mask = (num_pages * 1 << granule) - 1};
45
+ * to take the IMPDEF option to make memory accesses to the stack
63
+
46
+ * slots that correspond to the D16-D31 registers (discarding
64
+ g_hash_table_foreach_remove(s->iotlb,
47
+ * read data and writing UNKNOWN values), so for us the T2
65
+ smmu_hash_remove_by_asid_iova,
48
+ * encoding behaves identically to the T1 encoding.
66
+ &info);
49
+ */
67
}
50
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
68
51
+ return false;
69
inline void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid)
52
+ }
70
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
53
+ } else {
71
index XXXXXXX..XXXXXXX 100644
54
+ /*
72
--- a/hw/arm/smmuv3.c
55
+ * T1 encoding ({D0-D15} reglist); undef if we have 32 Dregs.
73
+++ b/hw/arm/smmuv3.c
56
+ * This is currently architecturally impossible, but we add the
74
@@ -XXX,XX +XXX,XX @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
57
+ * check to stay in line with the pseudocode. Note that we must
75
uint16_t vmid = CMD_VMID(cmd);
58
+ * emit code for the UNDEF so it takes precedence over the NOCP.
76
bool leaf = CMD_LEAF(cmd);
59
+ */
77
uint8_t tg = CMD_TG(cmd);
60
+ if (dc_isar_feature(aa32_simd_r32, s)) {
78
- hwaddr num_pages = 1;
61
+ unallocated_encoding(s);
79
+ uint64_t first_page = 0, last_page;
62
+ return true;
80
+ uint64_t num_pages = 1;
63
+ }
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);
91
+
92
+ /* Split invalidations into ^2 range invalidations */
93
+ last_page = num_pages - 1;
94
+ while (num_pages) {
95
+ uint8_t granule = tg * 2 + 10;
96
+ uint64_t mask, count;
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);
64
+ }
108
+ }
65
+
109
}
66
/*
110
67
* If not secure, UNDEF. We must emit code for this
111
static int smmuv3_cmdq_consume(SMMUv3State *s)
68
* rather than returning false so that this takes
69
--
112
--
70
2.20.1
113
2.20.1
71
114
72
115
diff view generated by jsdifflib
1
v8.1M introduces a new TRD flag in the CCR register, which enables
1
From: Eric Auger <eric.auger@redhat.com>
2
checking for stack frame integrity signatures on SG instructions.
3
Add the code in the SG insn implementation for the new behaviour.
4
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
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-24-peter.maydell@linaro.org
8
---
16
---
9
target/arm/m_helper.c | 86 +++++++++++++++++++++++++++++++++++++++++++
17
hw/arm/smmu-internal.h | 5 +++++
10
1 file changed, 86 insertions(+)
18
hw/arm/smmuv3.c | 34 ++++++++++++++++++++--------------
19
2 files changed, 25 insertions(+), 14 deletions(-)
11
20
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
21
diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h
13
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/m_helper.c
23
--- a/hw/arm/smmu-internal.h
15
+++ b/target/arm/m_helper.c
24
+++ b/hw/arm/smmu-internal.h
16
@@ -XXX,XX +XXX,XX @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx,
25
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUIOTLBPageInvInfo {
17
return true;
26
uint64_t mask;
27
} SMMUIOTLBPageInvInfo;
28
29
+typedef struct SMMUSIDRange {
30
+ uint32_t start;
31
+ uint32_t end;
32
+} SMMUSIDRange;
33
+
34
#endif
35
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/arm/smmuv3.c
38
+++ b/hw/arm/smmuv3.c
39
@@ -XXX,XX +XXX,XX @@
40
41
#include "hw/arm/smmuv3.h"
42
#include "smmuv3-internal.h"
43
+#include "smmu-internal.h"
44
45
/**
46
* smmuv3_trigger_irq - pulse @irq if enabled and update
47
@@ -XXX,XX +XXX,XX @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
48
}
18
}
49
}
19
50
20
+static bool v7m_read_sg_stack_word(ARMCPU *cpu, ARMMMUIdx mmu_idx,
51
+static gboolean
21
+ uint32_t addr, uint32_t *spdata)
52
+smmuv3_invalidate_ste(gpointer key, gpointer value, gpointer user_data)
22
+{
53
+{
23
+ /*
54
+ SMMUDevice *sdev = (SMMUDevice *)key;
24
+ * Read a word of data from the stack for the SG instruction,
55
+ uint32_t sid = smmu_get_sid(sdev);
25
+ * writing the value into *spdata. If the load succeeds, return
56
+ SMMUSIDRange *sid_range = (SMMUSIDRange *)user_data;
26
+ * true; otherwise pend an appropriate exception and return false.
27
+ * (We can't use data load helpers here that throw an exception
28
+ * because of the context we're called in, which is halfway through
29
+ * arm_v7m_cpu_do_interrupt().)
30
+ */
31
+ CPUState *cs = CPU(cpu);
32
+ CPUARMState *env = &cpu->env;
33
+ MemTxAttrs attrs = {};
34
+ MemTxResult txres;
35
+ target_ulong page_size;
36
+ hwaddr physaddr;
37
+ int prot;
38
+ ARMMMUFaultInfo fi = {};
39
+ ARMCacheAttrs cacheattrs = {};
40
+ uint32_t value;
41
+
57
+
42
+ if (get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &physaddr,
58
+ if (sid < sid_range->start || sid > sid_range->end) {
43
+ &attrs, &prot, &page_size, &fi, &cacheattrs)) {
44
+ /* MPU/SAU lookup failed */
45
+ if (fi.type == ARMFault_QEMU_SFault) {
46
+ qemu_log_mask(CPU_LOG_INT,
47
+ "...SecureFault during stack word read\n");
48
+ env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK | R_V7M_SFSR_SFARVALID_MASK;
49
+ env->v7m.sfar = addr;
50
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
51
+ } else {
52
+ qemu_log_mask(CPU_LOG_INT,
53
+ "...MemManageFault during stack word read\n");
54
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_DACCVIOL_MASK |
55
+ R_V7M_CFSR_MMARVALID_MASK;
56
+ env->v7m.mmfar[M_REG_S] = addr;
57
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM, false);
58
+ }
59
+ return false;
59
+ return false;
60
+ }
60
+ }
61
+ value = address_space_ldl(arm_addressspace(cs, attrs), physaddr,
61
+ trace_smmuv3_config_cache_inv(sid);
62
+ attrs, &txres);
63
+ if (txres != MEMTX_OK) {
64
+ /* BusFault trying to read the data */
65
+ qemu_log_mask(CPU_LOG_INT,
66
+ "...BusFault during stack word read\n");
67
+ env->v7m.cfsr[M_REG_NS] |=
68
+ (R_V7M_CFSR_PRECISERR_MASK | R_V7M_CFSR_BFARVALID_MASK);
69
+ env->v7m.bfar = addr;
70
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_BUS, false);
71
+ return false;
72
+ }
73
+
74
+ *spdata = value;
75
+ return true;
62
+ return true;
76
+}
63
+}
77
+
64
+
78
static bool v7m_handle_execute_nsc(ARMCPU *cpu)
65
static int smmuv3_cmdq_consume(SMMUv3State *s)
79
{
66
{
80
/*
67
SMMUState *bs = ARM_SMMU(s);
81
@@ -XXX,XX +XXX,XX @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu)
68
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
82
*/
69
}
83
qemu_log_mask(CPU_LOG_INT, "...really an SG instruction at 0x%08" PRIx32
70
case SMMU_CMD_CFGI_STE_RANGE: /* same as SMMU_CMD_CFGI_ALL */
84
", executing it\n", env->regs[15]);
71
{
85
+
72
- uint32_t start = CMD_SID(&cmd), end, i;
86
+ if (cpu_isar_feature(aa32_m_sec_state, cpu) &&
73
+ uint32_t start = CMD_SID(&cmd);
87
+ !arm_v7m_is_handler_mode(env)) {
74
uint8_t range = CMD_STE_RANGE(&cmd);
88
+ /*
75
+ uint64_t end = start + (1ULL << (range + 1)) - 1;
89
+ * v8.1M exception stack frame integrity check. Note that we
76
+ SMMUSIDRange sid_range = {start, end};
90
+ * must perform the memory access even if CCR_S.TRD is zero
77
91
+ * and we aren't going to check what the data loaded is.
78
if (CMD_SSEC(&cmd)) {
92
+ */
79
cmd_error = SMMU_CERROR_ILL;
93
+ uint32_t spdata, sp;
80
break;
94
+
81
}
95
+ /*
82
-
96
+ * We know we are currently NS, so the S stack pointers must be
83
- end = start + (1 << (range + 1)) - 1;
97
+ * in other_ss_{psp,msp}, not in regs[13]/other_sp.
84
trace_smmuv3_cmdq_cfgi_ste_range(start, end);
98
+ */
85
-
99
+ sp = v7m_using_psp(env) ? env->v7m.other_ss_psp : env->v7m.other_ss_msp;
86
- for (i = start; i <= end; i++) {
100
+ if (!v7m_read_sg_stack_word(cpu, mmu_idx, sp, &spdata)) {
87
- IOMMUMemoryRegion *mr = smmu_iommu_mr(bs, i);
101
+ /* Stack access failed and an exception has been pended */
88
- SMMUDevice *sdev;
102
+ return false;
89
-
103
+ }
90
- if (!mr) {
104
+
91
- continue;
105
+ if (env->v7m.ccr[M_REG_S] & R_V7M_CCR_TRD_MASK) {
92
- }
106
+ if (((spdata & ~1) == 0xfefa125a) ||
93
- sdev = container_of(mr, SMMUDevice, iommu);
107
+ !(env->v7m.control[M_REG_S] & 1)) {
94
- smmuv3_flush_config(sdev);
108
+ goto gen_invep;
95
- }
109
+ }
96
+ g_hash_table_foreach_remove(bs->configs, smmuv3_invalidate_ste,
110
+ }
97
+ &sid_range);
111
+ }
98
break;
112
+
99
}
113
env->regs[14] &= ~1;
100
case SMMU_CMD_CFGI_CD:
114
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
115
switch_v7m_security_state(env, true);
116
--
101
--
117
2.20.1
102
2.20.1
118
103
119
104
diff view generated by jsdifflib
New patch
1
From: Eric Auger <eric.auger@redhat.com>
1
2
3
Convert all sid printouts to sid=0x%x.
4
5
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Message-id: 20210309102742.30442-8-eric.auger@redhat.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/arm/trace-events | 24 ++++++++++++------------
11
1 file changed, 12 insertions(+), 12 deletions(-)
12
13
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/trace-events
16
+++ b/hw/arm/trace-events
17
@@ -XXX,XX +XXX,XX @@ smmuv3_cmdq_opcode(const char *opcode) "<--- %s"
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 "
19
smmuv3_cmdq_consume_error(const char *cmd_name, uint8_t cmd_error) "Error on %s command execution: %d"
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)"
21
-smmuv3_record_event(const char *type, uint32_t sid) "%s sid=%d"
22
-smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "SID:0x%x features:0x%x, sid_split:0x%x"
23
+smmuv3_record_event(const char *type, uint32_t sid) "%s sid=0x%x"
24
+smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "sid=0x%x features:0x%x, sid_split:0x%x"
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"
26
smmuv3_get_ste(uint64_t addr) "STE addr: 0x%"PRIx64
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"
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"
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"
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"
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"
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"
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"
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"
35
smmuv3_get_cd(uint64_t addr) "CD addr: 0x%"PRIx64
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
56
--
57
2.20.1
58
59
diff view generated by jsdifflib
1
For M-profile before v8.1M, the only valid register for VMSR/VMRS is
1
From: Richard Henderson <richard.henderson@linaro.org>
2
the FPSCR. We have a comment that states this, but the actual logic
3
to forbid accesses for any other register value is missing, so we
4
would end up with A-profile style behaviour. Add the missing check.
5
2
3
Missed out on compressing the second half of a predicate
4
with length vl % 512 > 256.
5
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>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20210309155305.11301-2-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
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-7-peter.maydell@linaro.org
9
---
16
---
10
target/arm/translate-vfp.c.inc | 5 ++++-
17
target/arm/sve_helper.c | 30 +++++++++++++++++++++---------
11
1 file changed, 4 insertions(+), 1 deletion(-)
18
1 file changed, 21 insertions(+), 9 deletions(-)
12
19
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
20
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
14
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
22
--- a/target/arm/sve_helper.c
16
+++ b/target/arm/translate-vfp.c.inc
23
+++ b/target/arm/sve_helper.c
17
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
24
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_uzp_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
18
* Accesses to R15 are UNPREDICTABLE; we choose to undef.
25
if (oprsz <= 8) {
19
* (FPSCR -> r15 is a special case which writes to the PSR flags.)
26
l = compress_bits(n[0] >> odd, esz);
20
*/
27
h = compress_bits(m[0] >> odd, esz);
21
- if (a->rt == 15 && (!a->l || a->reg != ARM_VFP_FPSCR)) {
28
- d[0] = extract64(l + (h << (4 * oprsz)), 0, 8 * oprsz);
22
+ if (a->reg != ARM_VFP_FPSCR) {
29
+ d[0] = l | (h << (4 * oprsz));
23
+ return false;
30
} else {
24
+ }
31
ARMPredicateReg tmp_m;
25
+ if (a->rt == 15 && !a->l) {
32
intptr_t oprsz_16 = oprsz / 16;
26
return false;
33
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_uzp_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
34
h = n[2 * i + 1];
35
l = compress_bits(l >> odd, esz);
36
h = compress_bits(h >> odd, esz);
37
- d[i] = l + (h << 32);
38
+ d[i] = l | (h << 32);
39
}
40
41
- /* For VL which is not a power of 2, the results from M do not
42
- align nicely with the uint64_t for D. Put the aligned results
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
}
27
}
83
}
28
}
84
}
29
--
85
--
30
2.20.1
86
2.20.1
31
87
32
88
diff view generated by jsdifflib
1
v8.1M introduces a new TRD flag in the CCR register, which enables
1
From: Richard Henderson <richard.henderson@linaro.org>
2
checking for stack frame integrity signatures on SG instructions.
3
This bit is not banked, and is always RAZ/WI to Non-secure code.
4
Adjust the code for handling CCR reads and writes to handle this.
5
2
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>
12
Signed-off-by: Richard Henderson <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
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-23-peter.maydell@linaro.org
9
---
16
---
10
target/arm/cpu.h | 2 ++
17
target/arm/sve_helper.c | 25 ++++++++++++++-----------
11
hw/intc/armv7m_nvic.c | 26 ++++++++++++++++++--------
18
1 file changed, 14 insertions(+), 11 deletions(-)
12
2 files changed, 20 insertions(+), 8 deletions(-)
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 @@ FIELD(V7M_CCR, STKOFHFNMIGN, 10, 1)
24
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_zip_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
19
FIELD(V7M_CCR, DC, 16, 1)
25
intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
20
FIELD(V7M_CCR, IC, 17, 1)
26
int esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
21
FIELD(V7M_CCR, BP, 18, 1)
27
intptr_t high = FIELD_EX32(pred_desc, PREDDESC, DATA);
22
+FIELD(V7M_CCR, LOB, 19, 1)
28
+ int esize = 1 << esz;
23
+FIELD(V7M_CCR, TRD, 20, 1)
29
uint64_t *d = vd;
24
30
intptr_t i;
25
/* V7M SCR bits */
31
26
FIELD(V7M_SCR, SLEEPONEXIT, 1, 1)
32
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_zip_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
27
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
33
mm = extract64(mm, high * half, half);
28
index XXXXXXX..XXXXXXX 100644
34
nn = expand_bits(nn, esz);
29
--- a/hw/intc/armv7m_nvic.c
35
mm = expand_bits(mm, esz);
30
+++ b/hw/intc/armv7m_nvic.c
36
- d[0] = nn + (mm << (1 << esz));
31
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
37
+ d[0] = nn | (mm << esize);
38
} else {
39
- ARMPredicateReg tmp_n, tmp_m;
40
+ ARMPredicateReg tmp;
41
42
/* We produce output faster than we consume input.
43
Therefore we must be mindful of possible overlap. */
44
- if ((vn - vd) < (uintptr_t)oprsz) {
45
- vn = memcpy(&tmp_n, vn, oprsz);
46
- }
47
- if ((vm - vd) < (uintptr_t)oprsz) {
48
- vm = memcpy(&tmp_m, vm, oprsz);
49
+ if (vd == vn) {
50
+ vn = memcpy(&tmp, vn, oprsz);
51
+ if (vd == vm) {
52
+ vm = vn;
53
+ }
54
+ } else if (vd == vm) {
55
+ vm = memcpy(&tmp, vm, oprsz);
32
}
56
}
33
return cpu->env.v7m.scr[attrs.secure];
57
if (high) {
34
case 0xd14: /* Configuration Control. */
58
high = oprsz >> 1;
35
- /* The BFHFNMIGN bit is the only non-banked bit; we
36
- * keep it in the non-secure copy of the register.
37
+ /*
38
+ * Non-banked bits: BFHFNMIGN (stored in the NS copy of the register)
39
+ * and TRD (stored in the S copy of the register)
40
*/
41
val = cpu->env.v7m.ccr[attrs.secure];
42
val |= cpu->env.v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK;
43
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
44
cpu->env.v7m.scr[attrs.secure] = value;
45
break;
46
case 0xd14: /* Configuration Control. */
47
+ {
48
+ uint32_t mask;
49
+
50
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
51
goto bad_offset;
52
}
59
}
53
60
54
/* Enforce RAZ/WI on reserved and must-RAZ/WI bits */
61
- if ((high & 3) == 0) {
55
- value &= (R_V7M_CCR_STKALIGN_MASK |
62
+ if ((oprsz & 7) == 0) {
56
- R_V7M_CCR_BFHFNMIGN_MASK |
63
uint32_t *n = vn, *m = vm;
57
- R_V7M_CCR_DIV_0_TRP_MASK |
64
high >>= 2;
58
- R_V7M_CCR_UNALIGN_TRP_MASK |
65
59
- R_V7M_CCR_USERSETMPEND_MASK |
66
- for (i = 0; i < DIV_ROUND_UP(oprsz, 8); i++) {
60
- R_V7M_CCR_NONBASETHRDENA_MASK);
67
+ for (i = 0; i < oprsz / 8; i++) {
61
+ mask = R_V7M_CCR_STKALIGN_MASK |
68
uint64_t nn = n[H4(high + i)];
62
+ R_V7M_CCR_BFHFNMIGN_MASK |
69
uint64_t mm = m[H4(high + i)];
63
+ R_V7M_CCR_DIV_0_TRP_MASK |
70
64
+ R_V7M_CCR_UNALIGN_TRP_MASK |
71
nn = expand_bits(nn, esz);
65
+ R_V7M_CCR_USERSETMPEND_MASK |
72
mm = expand_bits(mm, esz);
66
+ R_V7M_CCR_NONBASETHRDENA_MASK;
73
- d[i] = nn + (mm << (1 << esz));
67
+ if (arm_feature(&cpu->env, ARM_FEATURE_V8_1M) && attrs.secure) {
74
+ d[i] = nn | (mm << esize);
68
+ /* TRD is always RAZ/WI from NS */
75
}
69
+ mask |= R_V7M_CCR_TRD_MASK;
76
} else {
70
+ }
77
uint8_t *n = vn, *m = vm;
71
+ value &= mask;
78
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_zip_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
72
79
73
if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
80
nn = expand_bits(nn, esz);
74
/* v8M makes NONBASETHRDENA and STKALIGN be RES1 */
81
mm = expand_bits(mm, esz);
75
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
82
- d16[H2(i)] = nn + (mm << (1 << esz));
76
83
+ d16[H2(i)] = nn | (mm << esize);
77
cpu->env.v7m.ccr[attrs.secure] = value;
84
}
78
break;
85
}
79
+ }
86
}
80
case 0xd24: /* System Handler Control and State (SHCSR) */
81
if (!arm_feature(&cpu->env, ARM_FEATURE_V7)) {
82
goto bad_offset;
83
--
87
--
84
2.20.1
88
2.20.1
85
89
86
90
diff view generated by jsdifflib
1
We defined a constant name for the mask of NZCV bits in the FPCR/FPSCR
1
From: Richard Henderson <richard.henderson@linaro.org>
2
in the previous commit; use it in a couple of places in existing code,
3
where we're masking out everything except NZCV for the "load to Rt=15
4
sets CPSR.NZCV" special case.
5
2
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>
7
Signed-off-by: Richard Henderson <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
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-12-peter.maydell@linaro.org
9
---
10
---
10
target/arm/translate-vfp.c.inc | 4 ++--
11
target/arm/sve_helper.c | 4 ++--
11
1 file changed, 2 insertions(+), 2 deletions(-)
12
1 file changed, 2 insertions(+), 2 deletions(-)
12
13
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
16
--- a/target/arm/sve_helper.c
16
+++ b/target/arm/translate-vfp.c.inc
17
+++ b/target/arm/sve_helper.c
17
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
18
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_punpk_p)(void *vd, void *vn, uint32_t pred_desc)
18
* helper call for the "VMRS to CPSR.NZCV" insn.
19
high = oprsz >> 1;
19
*/
20
}
20
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
21
21
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
22
- if ((high & 3) == 0) {
22
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
23
+ if ((oprsz & 7) == 0) {
23
storefn(s, opaque, tmp);
24
uint32_t *n = vn;
24
break;
25
high >>= 2;
25
default:
26
26
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
27
- for (i = 0; i < DIV_ROUND_UP(oprsz, 8); i++) {
27
case ARM_VFP_FPSCR:
28
+ for (i = 0; i < oprsz / 8; i++) {
28
if (a->rt == 15) {
29
uint64_t nn = n[H4(high + i)];
29
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
30
d[i] = expand_bits(nn, 0);
30
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
31
}
31
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
32
} else {
33
tmp = tcg_temp_new_i32();
34
gen_helper_vfp_get_fpscr(tmp, cpu_env);
35
--
32
--
36
2.20.1
33
2.20.1
37
34
38
35
diff view generated by jsdifflib
1
From: Alex Chen <alex.chen@huawei.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We should use printf format specifier "%u" instead of "%d" for
3
Since b64ee454a4a0, all predicate operations should be
4
argument of type "unsigned int".
4
using these field macros for predicates.
5
5
6
Reported-by: Euler Robot <euler.robot@huawei.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
7
Message-id: 20210309155305.11301-5-richard.henderson@linaro.org
8
Message-id: 20201126111109.112238-5-alex.chen@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
hw/misc/imx6ul_ccm.c | 4 ++--
11
target/arm/sve_helper.c | 6 +++---
13
1 file changed, 2 insertions(+), 2 deletions(-)
12
target/arm/translate-sve.c | 7 +++----
13
2 files changed, 6 insertions(+), 7 deletions(-)
14
14
15
diff --git a/hw/misc/imx6ul_ccm.c b/hw/misc/imx6ul_ccm.c
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/misc/imx6ul_ccm.c
17
--- a/target/arm/sve_helper.c
18
+++ b/hw/misc/imx6ul_ccm.c
18
+++ b/target/arm/sve_helper.c
19
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_ccm_reg_name(uint32_t reg)
19
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_compact_d)(void *vd, void *vn, void *vg, uint32_t desc)
20
case CCM_CMEOR:
20
*/
21
return "CMEOR";
21
int32_t HELPER(sve_last_active_element)(void *vg, uint32_t pred_desc)
22
default:
22
{
23
- sprintf(unknown, "%d ?", reg);
23
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
24
+ sprintf(unknown, "%u ?", reg);
24
- intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
25
return unknown;
25
+ intptr_t words = DIV_ROUND_UP(FIELD_EX32(pred_desc, PREDDESC, OPRSZ), 8);
26
}
26
+ intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
27
28
- return last_active_element(vg, DIV_ROUND_UP(oprsz, 8), esz);
29
+ return last_active_element(vg, words, esz);
27
}
30
}
28
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_analog_reg_name(uint32_t reg)
31
29
case USB_ANALOG_DIGPROG:
32
void HELPER(sve_splice)(void *vd, void *vn, void *vm, void *vg, uint32_t desc)
30
return "USB_ANALOG_DIGPROG";
33
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
31
default:
34
index XXXXXXX..XXXXXXX 100644
32
- sprintf(unknown, "%d ?", reg);
35
--- a/target/arm/translate-sve.c
33
+ sprintf(unknown, "%u ?", reg);
36
+++ b/target/arm/translate-sve.c
34
return unknown;
37
@@ -XXX,XX +XXX,XX @@ static void find_last_active(DisasContext *s, TCGv_i32 ret, int esz, int pg)
35
}
38
*/
36
}
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);
37
--
52
--
38
2.20.1
53
2.20.1
39
54
40
55
diff view generated by jsdifflib
1
For v8.1M the architecture mandates that CPUs must provide at
1
From: Richard Henderson <richard.henderson@linaro.org>
2
least the "minimal RAS implementation" from the Reliability,
3
Availability and Serviceability extension. This consists of:
4
* an ESB instruction which is a NOP
5
-- since it is in the HINT space we need only add a comment
6
* an RFSR register which will RAZ/WI
7
* a RAZ/WI AIRCR.IESB bit
8
-- the code which handles writes to AIRCR does not allow setting
9
of RES0 bits, so we already treat this as RAZ/WI; add a comment
10
noting that this is deliberate
11
* minimal implementation of the RAS register block at 0xe0005000
12
-- this will be in a subsequent commit
13
* setting the ID_PFR0.RAS field to 0b0010
14
-- we will do this when we add the Cortex-M55 CPU model
15
2
3
Since b64ee454a4a0, all predicate operations should be
4
using these field macros for predicates.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210309155305.11301-6-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20201119215617.29887-26-peter.maydell@linaro.org
19
---
10
---
20
target/arm/cpu.h | 14 ++++++++++++++
11
target/arm/sve_helper.c | 30 ++++++++++++++----------------
21
target/arm/t32.decode | 4 ++++
12
target/arm/translate-sve.c | 4 ++--
22
hw/intc/armv7m_nvic.c | 13 +++++++++++++
13
2 files changed, 16 insertions(+), 18 deletions(-)
23
3 files changed, 31 insertions(+)
24
14
25
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
26
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/cpu.h
17
--- a/target/arm/sve_helper.c
28
+++ b/target/arm/cpu.h
18
+++ b/target/arm/sve_helper.c
29
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, LSM, 20, 4)
19
@@ -XXX,XX +XXX,XX @@ static uint32_t do_zero(ARMPredicateReg *d, intptr_t oprsz)
30
FIELD(ID_MMFR4, CCIDX, 24, 4)
20
void HELPER(sve_brkpa)(void *vd, void *vn, void *vm, void *vg,
31
FIELD(ID_MMFR4, EVT, 28, 4)
21
uint32_t pred_desc)
32
22
{
33
+FIELD(ID_PFR0, STATE0, 0, 4)
23
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
34
+FIELD(ID_PFR0, STATE1, 4, 4)
24
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
35
+FIELD(ID_PFR0, STATE2, 8, 4)
25
if (last_active_pred(vn, vg, oprsz)) {
36
+FIELD(ID_PFR0, STATE3, 12, 4)
26
compute_brk_z(vd, vm, vg, oprsz, true);
37
+FIELD(ID_PFR0, CSV2, 16, 4)
27
} else {
38
+FIELD(ID_PFR0, AMU, 20, 4)
28
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_brkpa)(void *vd, void *vn, void *vm, void *vg,
39
+FIELD(ID_PFR0, DIT, 24, 4)
29
uint32_t HELPER(sve_brkpas)(void *vd, void *vn, void *vm, void *vg,
40
+FIELD(ID_PFR0, RAS, 28, 4)
30
uint32_t pred_desc)
41
+
31
{
42
FIELD(ID_PFR1, PROGMOD, 0, 4)
32
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
43
FIELD(ID_PFR1, SECURITY, 4, 4)
33
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
44
FIELD(ID_PFR1, MPROGMOD, 8, 4)
34
if (last_active_pred(vn, vg, oprsz)) {
45
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
35
return compute_brks_z(vd, vm, vg, oprsz, true);
46
return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0;
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);
47
}
62
}
48
63
49
+static inline bool isar_feature_aa32_ras(const ARMISARegisters *id)
64
uint32_t HELPER(sve_brkas_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
50
+{
51
+ return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0;
52
+}
53
+
54
static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
55
{
65
{
56
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
66
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
57
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
67
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
68
return compute_brks_z(vd, vn, vg, oprsz, true);
69
}
70
71
void HELPER(sve_brkb_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
72
{
73
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
74
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
75
compute_brk_z(vd, vn, vg, oprsz, false);
76
}
77
78
uint32_t HELPER(sve_brkbs_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
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
58
index XXXXXXX..XXXXXXX 100644
132
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/t32.decode
133
--- a/target/arm/translate-sve.c
60
+++ b/target/arm/t32.decode
134
+++ b/target/arm/translate-sve.c
61
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
135
@@ -XXX,XX +XXX,XX @@ static bool do_brk3(DisasContext *s, arg_rprr_s *a,
62
# SEV 1111 0011 1010 1111 1000 0000 0000 0100
136
TCGv_ptr n = tcg_temp_new_ptr();
63
# SEVL 1111 0011 1010 1111 1000 0000 0000 0101
137
TCGv_ptr m = tcg_temp_new_ptr();
64
138
TCGv_ptr g = tcg_temp_new_ptr();
65
+ # For M-profile minimal-RAS ESB can be a NOP, which is the
139
- TCGv_i32 t = tcg_const_i32(vsz - 2);
66
+ # default behaviour since it is in the hint space.
140
+ TCGv_i32 t = tcg_const_i32(FIELD_DP32(0, PREDDESC, OPRSZ, vsz));
67
+ # ESB 1111 0011 1010 1111 1000 0000 0001 0000
141
68
+
142
tcg_gen_addi_ptr(d, cpu_env, pred_full_reg_offset(s, a->rd));
69
# The canonical nop ends in 0000 0000, but the whole rest
143
tcg_gen_addi_ptr(n, cpu_env, pred_full_reg_offset(s, a->rn));
70
# of the space is "reserved hint, behaves as nop".
144
@@ -XXX,XX +XXX,XX @@ static bool do_brk2(DisasContext *s, arg_rpr_s *a,
71
NOP 1111 0011 1010 1111 1000 0000 ---- ----
145
TCGv_ptr d = tcg_temp_new_ptr();
72
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
146
TCGv_ptr n = tcg_temp_new_ptr();
73
index XXXXXXX..XXXXXXX 100644
147
TCGv_ptr g = tcg_temp_new_ptr();
74
--- a/hw/intc/armv7m_nvic.c
148
- TCGv_i32 t = tcg_const_i32(vsz - 2);
75
+++ b/hw/intc/armv7m_nvic.c
149
+ TCGv_i32 t = tcg_const_i32(FIELD_DP32(0, PREDDESC, OPRSZ, vsz));
76
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
150
77
return 0;
151
tcg_gen_addi_ptr(d, cpu_env, pred_full_reg_offset(s, a->rd));
78
}
152
tcg_gen_addi_ptr(n, cpu_env, pred_full_reg_offset(s, a->rn));
79
return cpu->env.v7m.sfar;
80
+ case 0xf04: /* RFSR */
81
+ if (!cpu_isar_feature(aa32_ras, cpu)) {
82
+ goto bad_offset;
83
+ }
84
+ /* We provide minimal-RAS only: RFSR is RAZ/WI */
85
+ return 0;
86
case 0xf34: /* FPCCR */
87
if (!cpu_isar_feature(aa32_vfp_simd, cpu)) {
88
return 0;
89
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
90
R_V7M_AIRCR_PRIGROUP_SHIFT,
91
R_V7M_AIRCR_PRIGROUP_LENGTH);
92
}
93
+ /* AIRCR.IESB is RAZ/WI because we implement only minimal RAS */
94
if (attrs.secure) {
95
/* These bits are only writable by secure */
96
cpu->env.v7m.aircr = value &
97
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
98
}
99
break;
100
}
101
+ case 0xf04: /* RFSR */
102
+ if (!cpu_isar_feature(aa32_ras, cpu)) {
103
+ goto bad_offset;
104
+ }
105
+ /* We provide minimal-RAS only: RFSR is RAZ/WI */
106
+ break;
107
case 0xf34: /* FPCCR */
108
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
109
/* Not all bits here are banked. */
110
--
153
--
111
2.20.1
154
2.20.1
112
155
113
156
diff view generated by jsdifflib
1
From: Alex Chen <alex.chen@huawei.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We should use printf format specifier "%u" instead of "%d" for
3
Since b64ee454a4a0, all predicate operations should be
4
argument of type "unsigned int".
4
using these field macros for predicates.
5
5
6
Reported-by: Euler Robot <euler.robot@huawei.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
7
Message-id: 20210309155305.11301-7-richard.henderson@linaro.org
8
Message-id: 20201126111109.112238-4-alex.chen@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
hw/misc/imx6_ccm.c | 20 ++++++++++----------
11
target/arm/sve_helper.c | 6 +++---
13
hw/misc/imx6_src.c | 2 +-
12
target/arm/translate-sve.c | 6 +++---
14
2 files changed, 11 insertions(+), 11 deletions(-)
13
2 files changed, 6 insertions(+), 6 deletions(-)
15
14
16
diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/misc/imx6_ccm.c
17
--- a/target/arm/sve_helper.c
19
+++ b/hw/misc/imx6_ccm.c
18
+++ b/target/arm/sve_helper.c
20
@@ -XXX,XX +XXX,XX @@ static const char *imx6_ccm_reg_name(uint32_t reg)
19
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sve_brkns)(void *vd, void *vn, void *vg, uint32_t pred_desc)
21
case CCM_CMEOR:
20
22
return "CMEOR";
21
uint64_t HELPER(sve_cntp)(void *vn, void *vg, uint32_t pred_desc)
23
default:
22
{
24
- sprintf(unknown, "%d ?", reg);
23
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
25
+ sprintf(unknown, "%u ?", reg);
24
- intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
26
return unknown;
25
+ intptr_t words = DIV_ROUND_UP(FIELD_EX32(pred_desc, PREDDESC, OPRSZ), 8);
26
+ intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
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);
27
}
34
}
28
}
35
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
29
@@ -XXX,XX +XXX,XX @@ static const char *imx6_analog_reg_name(uint32_t reg)
30
case USB_ANALOG_DIGPROG:
31
return "USB_ANALOG_DIGPROG";
32
default:
33
- sprintf(unknown, "%d ?", reg);
34
+ sprintf(unknown, "%u ?", reg);
35
return unknown;
36
}
37
}
38
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_clk(IMX6CCMState *dev)
39
freq *= 20;
40
}
41
42
- DPRINTF("freq = %d\n", (uint32_t)freq);
43
+ DPRINTF("freq = %u\n", (uint32_t)freq);
44
45
return freq;
46
}
47
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_pfd0_clk(IMX6CCMState *dev)
48
freq = imx6_analog_get_pll2_clk(dev) * 18
49
/ EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD0_FRAC);
50
51
- DPRINTF("freq = %d\n", (uint32_t)freq);
52
+ DPRINTF("freq = %u\n", (uint32_t)freq);
53
54
return freq;
55
}
56
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_pfd2_clk(IMX6CCMState *dev)
57
freq = imx6_analog_get_pll2_clk(dev) * 18
58
/ EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD2_FRAC);
59
60
- DPRINTF("freq = %d\n", (uint32_t)freq);
61
+ DPRINTF("freq = %u\n", (uint32_t)freq);
62
63
return freq;
64
}
65
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_periph_clk(IMX6CCMState *dev)
66
break;
67
}
68
69
- DPRINTF("freq = %d\n", (uint32_t)freq);
70
+ DPRINTF("freq = %u\n", (uint32_t)freq);
71
72
return freq;
73
}
74
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_ahb_clk(IMX6CCMState *dev)
75
freq = imx6_analog_get_periph_clk(dev)
76
/ (1 + EXTRACT(dev->ccm[CCM_CBCDR], AHB_PODF));
77
78
- DPRINTF("freq = %d\n", (uint32_t)freq);
79
+ DPRINTF("freq = %u\n", (uint32_t)freq);
80
81
return freq;
82
}
83
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_ipg_clk(IMX6CCMState *dev)
84
freq = imx6_ccm_get_ahb_clk(dev)
85
/ (1 + EXTRACT(dev->ccm[CCM_CBCDR], IPG_PODF));
86
87
- DPRINTF("freq = %d\n", (uint32_t)freq);
88
+ DPRINTF("freq = %u\n", (uint32_t)freq);
89
90
return freq;
91
}
92
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_per_clk(IMX6CCMState *dev)
93
freq = imx6_ccm_get_ipg_clk(dev)
94
/ (1 + EXTRACT(dev->ccm[CCM_CSCMR1], PERCLK_PODF));
95
96
- DPRINTF("freq = %d\n", (uint32_t)freq);
97
+ DPRINTF("freq = %u\n", (uint32_t)freq);
98
99
return freq;
100
}
101
@@ -XXX,XX +XXX,XX @@ static uint32_t imx6_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
102
break;
103
}
104
105
- DPRINTF("Clock = %d) = %d\n", clock, freq);
106
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
107
108
return freq;
109
}
110
diff --git a/hw/misc/imx6_src.c b/hw/misc/imx6_src.c
111
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
112
--- a/hw/misc/imx6_src.c
37
--- a/target/arm/translate-sve.c
113
+++ b/hw/misc/imx6_src.c
38
+++ b/target/arm/translate-sve.c
114
@@ -XXX,XX +XXX,XX @@ static const char *imx6_src_reg_name(uint32_t reg)
39
@@ -XXX,XX +XXX,XX @@ static void do_cntp(DisasContext *s, TCGv_i64 val, int esz, int pn, int pg)
115
case SRC_GPR10:
40
} else {
116
return "SRC_GPR10";
41
TCGv_ptr t_pn = tcg_temp_new_ptr();
117
default:
42
TCGv_ptr t_pg = tcg_temp_new_ptr();
118
- sprintf(unknown, "%d ?", reg);
43
- unsigned desc;
119
+ sprintf(unknown, "%u ?", reg);
44
+ unsigned desc = 0;
120
return unknown;
45
TCGv_i32 t_desc;
121
}
46
122
}
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));
123
--
54
--
124
2.20.1
55
2.20.1
125
56
126
57
diff view generated by jsdifflib
1
From: Alex Chen <alex.chen@huawei.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We should use printf format specifier "%u" instead of "%d" for
3
Since b64ee454a4a0, all predicate operations should be
4
argument of type "unsigned int".
4
using these field macros for predicates.
5
5
6
Reported-by: Euler Robot <euler.robot@huawei.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
7
Message-id: 20210309155305.11301-8-richard.henderson@linaro.org
8
Message-id: 20201126111109.112238-3-alex.chen@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
hw/misc/imx31_ccm.c | 14 +++++++-------
11
target/arm/sve_helper.c | 4 ++--
13
hw/misc/imx_ccm.c | 4 ++--
12
target/arm/translate-sve.c | 7 ++++---
14
2 files changed, 9 insertions(+), 9 deletions(-)
13
2 files changed, 6 insertions(+), 5 deletions(-)
15
14
16
diff --git a/hw/misc/imx31_ccm.c b/hw/misc/imx31_ccm.c
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/misc/imx31_ccm.c
17
--- a/target/arm/sve_helper.c
19
+++ b/hw/misc/imx31_ccm.c
18
+++ b/target/arm/sve_helper.c
20
@@ -XXX,XX +XXX,XX @@ static const char *imx31_ccm_reg_name(uint32_t reg)
19
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(sve_cntp)(void *vn, void *vg, uint32_t pred_desc)
21
case IMX31_CCM_PDR2_REG:
20
22
return "PDR2";
21
uint32_t HELPER(sve_while)(void *vd, uint32_t count, uint32_t pred_desc)
23
default:
22
{
24
- sprintf(unknown, "[%d ?]", reg);
23
- uintptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
25
+ sprintf(unknown, "[%u ?]", reg);
24
- intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
26
return unknown;
25
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
27
}
26
+ intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
28
}
27
uint64_t esz_mask = pred_esz_masks[esz];
29
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_pll_ref_clk(IMXCCMState *dev)
28
ARMPredicateReg *d = vd;
30
freq = CKIH_FREQ;
29
uint32_t flags;
31
}
30
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
32
33
- DPRINTF("freq = %d\n", freq);
34
+ DPRINTF("freq = %u\n", freq);
35
36
return freq;
37
}
38
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_mpll_clk(IMXCCMState *dev)
39
freq = imx_ccm_calc_pll(s->reg[IMX31_CCM_MPCTL_REG],
40
imx31_ccm_get_pll_ref_clk(dev));
41
42
- DPRINTF("freq = %d\n", freq);
43
+ DPRINTF("freq = %u\n", freq);
44
45
return freq;
46
}
47
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_mcu_main_clk(IMXCCMState *dev)
48
freq = imx31_ccm_get_mpll_clk(dev);
49
}
50
51
- DPRINTF("freq = %d\n", freq);
52
+ DPRINTF("freq = %u\n", freq);
53
54
return freq;
55
}
56
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_hclk_clk(IMXCCMState *dev)
57
freq = imx31_ccm_get_mcu_main_clk(dev)
58
/ (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], MAX));
59
60
- DPRINTF("freq = %d\n", freq);
61
+ DPRINTF("freq = %u\n", freq);
62
63
return freq;
64
}
65
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_ipg_clk(IMXCCMState *dev)
66
freq = imx31_ccm_get_hclk_clk(dev)
67
/ (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], IPG));
68
69
- DPRINTF("freq = %d\n", freq);
70
+ DPRINTF("freq = %u\n", freq);
71
72
return freq;
73
}
74
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
75
break;
76
}
77
78
- DPRINTF("Clock = %d) = %d\n", clock, freq);
79
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
80
81
return freq;
82
}
83
diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c
84
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
85
--- a/hw/misc/imx_ccm.c
32
--- a/target/arm/translate-sve.c
86
+++ b/hw/misc/imx_ccm.c
33
+++ b/target/arm/translate-sve.c
87
@@ -XXX,XX +XXX,XX @@ uint32_t imx_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
34
@@ -XXX,XX +XXX,XX @@ static bool trans_WHILE(DisasContext *s, arg_WHILE *a)
88
freq = klass->get_clock_frequency(dev, clock);
35
TCGv_i64 op0, op1, t0, t1, tmax;
89
}
36
TCGv_i32 t2, t3;
90
37
TCGv_ptr ptr;
91
- DPRINTF("(clock = %d) = %d\n", clock, freq);
38
- unsigned desc, vsz = vec_full_reg_size(s);
92
+ DPRINTF("(clock = %d) = %u\n", clock, freq);
39
+ unsigned vsz = vec_full_reg_size(s);
93
40
+ unsigned desc = 0;
94
return freq;
41
TCGCond cond;
95
}
42
96
@@ -XXX,XX +XXX,XX @@ uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq)
43
if (!sve_access_check(s)) {
97
freq = ((2 * (base_freq >> 10) * (mfi * mfd + mfn)) /
44
@@ -XXX,XX +XXX,XX @@ static bool trans_WHILE(DisasContext *s, arg_WHILE *a)
98
(mfd * pd)) << 10;
45
/* Scale elements to bits. */
99
46
tcg_gen_shli_i32(t2, t2, a->esz);
100
- DPRINTF("(pllreg = 0x%08x, base_freq = %d) = %d\n", pllreg, base_freq,
47
101
+ DPRINTF("(pllreg = 0x%08x, base_freq = %u) = %d\n", pllreg, base_freq,
48
- desc = (vsz / 8) - 2;
102
freq);
49
- desc = deposit32(desc, SIMD_DATA_SHIFT, 2, a->esz);
103
50
+ desc = FIELD_DP32(desc, PREDDESC, OPRSZ, vsz / 8);
104
return freq;
51
+ desc = FIELD_DP32(desc, PREDDESC, ESZ, a->esz);
52
t3 = tcg_const_i32(desc);
53
54
ptr = tcg_temp_new_ptr();
105
--
55
--
106
2.20.1
56
2.20.1
107
57
108
58
diff view generated by jsdifflib
1
From: Alex Chen <alex.chen@huawei.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We should use printf format specifier "%u" instead of "%d" for
3
With the reduction operations, we intentionally increase maxsz to
4
argument of type "unsigned int".
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.
5
8
6
Reported-by: Euler Robot <euler.robot@huawei.com>
9
Pass the power-of-two value in the simd_data field instead.
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
10
8
Message-id: 20201126111109.112238-2-alex.chen@huawei.com
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210309155305.11301-9-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
15
---
12
hw/misc/imx25_ccm.c | 12 ++++++------
16
target/arm/sve_helper.c | 2 +-
13
1 file changed, 6 insertions(+), 6 deletions(-)
17
target/arm/translate-sve.c | 2 +-
18
2 files changed, 2 insertions(+), 2 deletions(-)
14
19
15
diff --git a/hw/misc/imx25_ccm.c b/hw/misc/imx25_ccm.c
20
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
16
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/misc/imx25_ccm.c
22
--- a/target/arm/sve_helper.c
18
+++ b/hw/misc/imx25_ccm.c
23
+++ b/target/arm/sve_helper.c
19
@@ -XXX,XX +XXX,XX @@ static const char *imx25_ccm_reg_name(uint32_t reg)
24
@@ -XXX,XX +XXX,XX @@ static TYPE NAME##_reduce(TYPE *data, float_status *status, uintptr_t n) \
20
case IMX25_CCM_LPIMR1_REG:
25
} \
21
return "lpimr1";
26
uint64_t HELPER(NAME)(void *vn, void *vg, void *vs, uint32_t desc) \
22
default:
27
{ \
23
- sprintf(unknown, "[%d ?]", reg);
28
- uintptr_t i, oprsz = simd_oprsz(desc), maxsz = simd_maxsz(desc); \
24
+ sprintf(unknown, "[%u ?]", reg);
29
+ uintptr_t i, oprsz = simd_oprsz(desc), maxsz = simd_data(desc); \
25
return unknown;
30
TYPE data[sizeof(ARMVectorReg) / sizeof(TYPE)]; \
26
}
31
for (i = 0; i < oprsz; ) { \
27
}
32
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
28
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mpll_clk(IMXCCMState *dev)
33
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
29
freq = imx_ccm_calc_pll(s->reg[IMX25_CCM_MPCTL_REG], CKIH_FREQ);
34
index XXXXXXX..XXXXXXX 100644
30
}
35
--- a/target/arm/translate-sve.c
31
36
+++ b/target/arm/translate-sve.c
32
- DPRINTF("freq = %d\n", freq);
37
@@ -XXX,XX +XXX,XX @@ static void do_reduce(DisasContext *s, arg_rpr_esz *a,
33
+ DPRINTF("freq = %u\n", freq);
38
{
34
39
unsigned vsz = vec_full_reg_size(s);
35
return freq;
40
unsigned p2vsz = pow2ceil(vsz);
36
}
41
- TCGv_i32 t_desc = tcg_const_i32(simd_desc(vsz, p2vsz, 0));
37
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mcu_clk(IMXCCMState *dev)
42
+ TCGv_i32 t_desc = tcg_const_i32(simd_desc(vsz, vsz, p2vsz));
38
43
TCGv_ptr t_zn, t_pg, status;
39
freq = freq / (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], ARM_CLK_DIV));
44
TCGv_i64 temp;
40
45
41
- DPRINTF("freq = %d\n", freq);
42
+ DPRINTF("freq = %u\n", freq);
43
44
return freq;
45
}
46
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_ahb_clk(IMXCCMState *dev)
47
freq = imx25_ccm_get_mcu_clk(dev)
48
/ (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], AHB_CLK_DIV));
49
50
- DPRINTF("freq = %d\n", freq);
51
+ DPRINTF("freq = %u\n", freq);
52
53
return freq;
54
}
55
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_ipg_clk(IMXCCMState *dev)
56
57
freq = imx25_ccm_get_ahb_clk(dev) / 2;
58
59
- DPRINTF("freq = %d\n", freq);
60
+ DPRINTF("freq = %u\n", freq);
61
62
return freq;
63
}
64
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
65
break;
66
}
67
68
- DPRINTF("Clock = %d) = %d\n", clock, freq);
69
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
70
71
return freq;
72
}
73
--
46
--
74
2.20.1
47
2.20.1
75
48
76
49
diff view generated by jsdifflib
1
Implement the v8.1M VSCCLRM insn, which zeros floating point
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
registers if there is an active floating point context.
3
This requires support in write_neon_element32() for the MO_32
4
element size, so add it.
5
2
6
Because we want to use arm_gen_condlabel(), we need to move
3
Currently the emulated EMAC for sun8i always traverses the transmit queue
7
the definition of that function up in translate.c so it is
4
from the head when transferring packets. It searches for a list of consecutive
8
before the #include of translate-vfp.c.inc.
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.
9
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
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20201119215617.29887-5-peter.maydell@linaro.org
13
---
23
---
14
target/arm/cpu.h | 9 ++++
24
hw/net/allwinner-sun8i-emac.c | 62 +++++++++++++++++++----------------
15
target/arm/m-nocp.decode | 8 +++-
25
1 file changed, 34 insertions(+), 28 deletions(-)
16
target/arm/translate.c | 21 +++++----
17
target/arm/translate-vfp.c.inc | 84 ++++++++++++++++++++++++++++++++++
18
4 files changed, 111 insertions(+), 11 deletions(-)
19
26
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
27
diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c
21
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.h
29
--- a/hw/net/allwinner-sun8i-emac.c
23
+++ b/target/arm/cpu.h
30
+++ b/hw/net/allwinner-sun8i-emac.c
24
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
31
@@ -XXX,XX +XXX,XX @@ static void allwinner_sun8i_emac_update_irq(AwSun8iEmacState *s)
25
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
32
qemu_set_irq(s->irq, (s->int_sta & s->int_en) != 0);
26
}
33
}
27
34
28
+static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id)
35
-static uint32_t allwinner_sun8i_emac_next_desc(AwSun8iEmacState *s,
36
- FrameDescriptor *desc,
37
- size_t min_size)
38
+static bool allwinner_sun8i_emac_desc_owned(FrameDescriptor *desc,
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)
29
+{
62
+{
30
+ /*
63
+ dma_memory_read(&s->dma_as, phys_addr, desc, sizeof(*desc));
31
+ * Return true if M-profile state handling insns
32
+ * (VSCCLRM, CLRM, FPCTX access insns) are implemented
33
+ */
34
+ return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3;
35
+}
64
+}
36
+
65
+
37
static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
66
+static uint32_t allwinner_sun8i_emac_next_desc(AwSun8iEmacState *s,
38
{
67
+ FrameDescriptor *desc)
39
/* Sadly this is encoded differently for A-profile and M-profile */
40
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/m-nocp.decode
43
+++ b/target/arm/m-nocp.decode
44
@@ -XXX,XX +XXX,XX @@
45
# If the coprocessor is not present or disabled then we will generate
46
# the NOCP exception; otherwise we let the insn through to the main decode.
47
48
+%vd_dp 22:1 12:4
49
+%vd_sp 12:4 22:1
50
+
51
&nocp cp
52
53
{
54
# Special cases which do not take an early NOCP: VLLDM and VLSTM
55
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
56
- # TODO: VSCCLRM (new in v8.1M) is similar:
57
- #VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
58
+ # VSCCLRM (new in v8.1M) is similar:
59
+ VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
60
+ VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
61
62
NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
63
NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
64
diff --git a/target/arm/translate.c b/target/arm/translate.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/translate.c
67
+++ b/target/arm/translate.c
68
@@ -XXX,XX +XXX,XX @@ void arm_translate_init(void)
69
a64_translate_init();
70
}
71
72
+/* Generate a label used for skipping this instruction */
73
+static void arm_gen_condlabel(DisasContext *s)
74
+{
68
+{
75
+ if (!s->condjmp) {
69
+ const uint32_t nxt = desc->next;
76
+ s->condlabel = gen_new_label();
70
+ allwinner_sun8i_emac_get_desc(s, desc, nxt);
77
+ s->condjmp = 1;
71
+ return nxt;
78
+ }
79
+}
72
+}
80
+
73
+
81
/* Flags for the disas_set_da_iss info argument:
74
+static uint32_t allwinner_sun8i_emac_find_desc(AwSun8iEmacState *s,
82
* lower bits hold the Rt register number, higher bits are flags.
75
+ FrameDescriptor *desc,
83
*/
76
+ uint32_t start_addr,
84
@@ -XXX,XX +XXX,XX @@ static void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop)
77
+ size_t min_size)
85
long off = neon_element_offset(reg, ele, memop);
78
{
86
79
uint32_t desc_addr = start_addr;
87
switch (memop) {
80
88
+ case MO_32:
81
/* Note that the list is a cycle. Last entry points back to the head. */
89
+ tcg_gen_st32_i64(src, cpu_env, off);
82
while (desc_addr != 0) {
90
+ break;
83
- dma_memory_read(&s->dma_as, desc_addr, desc, sizeof(*desc));
91
case MO_64:
84
+ allwinner_sun8i_emac_get_desc(s, desc, desc_addr);
92
tcg_gen_st_i64(src, cpu_env, off);
85
93
break;
86
- if ((desc->status & DESC_STATUS_CTL) &&
94
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
87
- (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) {
95
s->base.is_jmp = DISAS_UPDATE_EXIT;
88
+ if (allwinner_sun8i_emac_desc_owned(desc, min_size)) {
89
return desc_addr;
90
} else if (desc->next == start_addr) {
91
break;
92
@@ -XXX,XX +XXX,XX @@ static uint32_t allwinner_sun8i_emac_rx_desc(AwSun8iEmacState *s,
93
FrameDescriptor *desc,
94
size_t min_size)
95
{
96
- return allwinner_sun8i_emac_get_desc(s, desc, s->rx_desc_curr, min_size);
97
+ return allwinner_sun8i_emac_find_desc(s, desc, s->rx_desc_curr, min_size);
96
}
98
}
97
99
98
-/* Generate a label used for skipping this instruction */
100
static uint32_t allwinner_sun8i_emac_tx_desc(AwSun8iEmacState *s,
99
-static void arm_gen_condlabel(DisasContext *s)
101
- FrameDescriptor *desc,
100
-{
102
- size_t min_size)
101
- if (!s->condjmp) {
103
+ FrameDescriptor *desc)
102
- s->condlabel = gen_new_label();
103
- s->condjmp = 1;
104
- }
105
-}
106
-
107
/* Skip this instruction if the ARM condition is false */
108
static void arm_skip_unless(DisasContext *s, uint32_t cond)
109
{
104
{
110
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
105
- return allwinner_sun8i_emac_get_desc(s, desc, s->tx_desc_head, min_size);
111
index XXXXXXX..XXXXXXX 100644
106
+ allwinner_sun8i_emac_get_desc(s, desc, s->tx_desc_curr);
112
--- a/target/arm/translate-vfp.c.inc
107
+ return s->tx_desc_curr;
113
+++ b/target/arm/translate-vfp.c.inc
114
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
115
return true;
116
}
108
}
117
109
118
+static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
110
static void allwinner_sun8i_emac_flush_desc(AwSun8iEmacState *s,
119
+{
111
@@ -XXX,XX +XXX,XX @@ static ssize_t allwinner_sun8i_emac_receive(NetClientState *nc,
120
+ int btmreg, topreg;
112
bytes_left -= desc_bytes;
121
+ TCGv_i64 zero;
113
122
+ TCGv_i32 aspen, sfpa;
114
/* Move to the next descriptor */
123
+
115
- s->rx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc, 64);
124
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
116
+ s->rx_desc_curr = allwinner_sun8i_emac_find_desc(s, &desc, desc.next,
125
+ /* Before v8.1M, fall through in decode to NOCP check */
117
+ AW_SUN8I_EMAC_MIN_PKT_SZ);
126
+ return false;
118
if (!s->rx_desc_curr) {
127
+ }
119
/* Not enough buffer space available */
128
+
120
s->int_sta |= INT_STA_RX_BUF_UA;
129
+ /* Explicitly UNDEF because this takes precedence over NOCP */
121
@@ -XXX,XX +XXX,XX @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s)
130
+ if (!arm_dc_feature(s, ARM_FEATURE_M_MAIN) || !s->v8m_secure) {
122
size_t transmitted = 0;
131
+ unallocated_encoding(s);
123
static uint8_t packet_buf[2048];
132
+ return true;
124
133
+ }
125
- s->tx_desc_curr = allwinner_sun8i_emac_tx_desc(s, &desc, 0);
134
+
126
+ s->tx_desc_curr = allwinner_sun8i_emac_tx_desc(s, &desc);
135
+ if (!dc_isar_feature(aa32_vfp_simd, s)) {
127
136
+ /* NOP if we have neither FP nor MVE */
128
/* Read all transmit descriptors */
137
+ return true;
129
- while (s->tx_desc_curr != 0) {
138
+ }
130
+ while (allwinner_sun8i_emac_desc_owned(&desc, 0)) {
139
+
131
140
+ /*
132
/* Read from physical memory into packet buffer */
141
+ * If FPCCR.ASPEN != 0 && CONTROL_S.SFPA == 0 then there is no
133
bytes = desc.status2 & DESC_STATUS2_BUF_SIZE_MASK;
142
+ * active floating point context so we must NOP (without doing
134
@@ -XXX,XX +XXX,XX @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s)
143
+ * any lazy state preservation or the NOCP check).
135
packet_bytes = 0;
144
+ */
136
transmitted++;
145
+ aspen = load_cpu_field(v7m.fpccr[M_REG_S]);
137
}
146
+ sfpa = load_cpu_field(v7m.control[M_REG_S]);
138
- s->tx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc, 0);
147
+ tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
139
+ s->tx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc);
148
+ tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
140
}
149
+ tcg_gen_andi_i32(sfpa, sfpa, R_V7M_CONTROL_SFPA_MASK);
141
150
+ tcg_gen_or_i32(sfpa, sfpa, aspen);
142
/* Raise transmit completed interrupt */
151
+ arm_gen_condlabel(s);
152
+ tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel);
153
+
154
+ if (s->fp_excp_el != 0) {
155
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
156
+ syn_uncategorized(), s->fp_excp_el);
157
+ return true;
158
+ }
159
+
160
+ topreg = a->vd + a->imm - 1;
161
+ btmreg = a->vd;
162
+
163
+ /* Convert to Sreg numbers if the insn specified in Dregs */
164
+ if (a->size == 3) {
165
+ topreg = topreg * 2 + 1;
166
+ btmreg *= 2;
167
+ }
168
+
169
+ if (topreg > 63 || (topreg > 31 && !(topreg & 1))) {
170
+ /* UNPREDICTABLE: we choose to undef */
171
+ unallocated_encoding(s);
172
+ return true;
173
+ }
174
+
175
+ /* Silently ignore requests to clear D16-D31 if they don't exist */
176
+ if (topreg > 31 && !dc_isar_feature(aa32_simd_r32, s)) {
177
+ topreg = 31;
178
+ }
179
+
180
+ if (!vfp_access_check(s)) {
181
+ return true;
182
+ }
183
+
184
+ /* Zero the Sregs from btmreg to topreg inclusive. */
185
+ zero = tcg_const_i64(0);
186
+ if (btmreg & 1) {
187
+ write_neon_element64(zero, btmreg >> 1, 1, MO_32);
188
+ btmreg++;
189
+ }
190
+ for (; btmreg + 1 <= topreg; btmreg += 2) {
191
+ write_neon_element64(zero, btmreg >> 1, 0, MO_64);
192
+ }
193
+ if (btmreg == topreg) {
194
+ write_neon_element64(zero, btmreg >> 1, 0, MO_32);
195
+ btmreg++;
196
+ }
197
+ assert(btmreg == topreg + 1);
198
+ /* TODO: when MVE is implemented, zero VPR here */
199
+ return true;
200
+}
201
+
202
static bool trans_NOCP(DisasContext *s, arg_nocp *a)
203
{
204
/*
205
--
143
--
206
2.20.1
144
2.20.1
207
145
208
146
diff view generated by jsdifflib
1
In v8.1M a new exception return check is added which may cause a NOCP
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
UsageFault (see rule R_XLTP): before we clear s0..s15 and the FPSCR
3
we must check whether access to CP10 from the Security state of the
4
returning exception is disabled; if it is then we must take a fault.
5
2
6
(Note that for our implementation CPPWR is always RAZ/WI and so can
3
The image for Armbian 19.11.3 bionic has been removed from the armbian server.
7
never cause CP10 accesses to fail.)
4
Without the image as input the test arm_orangepi_bionic_19_11 cannot run.
8
5
9
The other v8.1M change to this register-clearing code is that if MVE
6
This commit removes the test completely and merges the code of the generic function
10
is implemented VPR must also be cleared, so add a TODO comment to
7
do_test_arm_orangepi_uboot_armbian back with the 20.08 test.
11
that effect.
12
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
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20201119215617.29887-20-peter.maydell@linaro.org
16
---
13
---
17
target/arm/m_helper.c | 22 +++++++++++++++++++++-
14
tests/acceptance/boot_linux_console.py | 72 ++++++++------------------
18
1 file changed, 21 insertions(+), 1 deletion(-)
15
1 file changed, 23 insertions(+), 49 deletions(-)
19
16
20
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
17
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
21
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/m_helper.c
19
--- a/tests/acceptance/boot_linux_console.py
23
+++ b/target/arm/m_helper.c
20
+++ b/tests/acceptance/boot_linux_console.py
24
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
21
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_sd(self):
25
v7m_exception_taken(cpu, excret, true, false);
22
# Wait for VM to shut down gracefully
26
return;
23
self.vm.wait()
27
} else {
24
28
- /* Clear s0..s15 and FPSCR */
25
- def do_test_arm_orangepi_uboot_armbian(self, image_path):
29
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
26
+ @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
30
+ /* v8.1M adds this NOCP check */
27
+ 'Test artifacts fetched from unreliable apt.armbian.com')
31
+ bool nsacr_pass = exc_secure ||
28
+ @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
32
+ extract32(env->v7m.nsacr, 10, 1);
29
+ def test_arm_orangepi_bionic_20_08(self):
33
+ bool cpacr_pass = v7m_cpacr_pass(env, exc_secure, true);
30
+ """
34
+ if (!nsacr_pass) {
31
+ :avocado: tags=arch:arm
35
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, true);
32
+ :avocado: tags=machine:orangepi-pc
36
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_NOCP_MASK;
33
+ :avocado: tags=device:sd
37
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
34
+ """
38
+ "stackframe: NSACR prevents clearing FPU registers\n");
35
+
39
+ v7m_exception_taken(cpu, excret, true, false);
36
+ # This test download a 275 MiB compressed image and expand it
40
+ } else if (!cpacr_pass) {
37
+ # to 1036 MiB, but the underlying filesystem is 1552 MiB...
41
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
38
+ # As we expand it to 2 GiB we are safe.
42
+ exc_secure);
39
+
43
+ env->v7m.cfsr[exc_secure] |= R_V7M_CFSR_NOCP_MASK;
40
+ image_url = ('https://dl.armbian.com/orangepipc/archive/'
44
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
41
+ 'Armbian_20.08.1_Orangepipc_bionic_current_5.8.5.img.xz')
45
+ "stackframe: CPACR prevents clearing FPU registers\n");
42
+ image_hash = ('b4d6775f5673486329e45a0586bf06b6'
46
+ v7m_exception_taken(cpu, excret, true, false);
43
+ 'dbe792199fd182ac6b9c7bb6c7d3e6dd')
47
+ }
44
+ image_path_xz = self.fetch_asset(image_url, asset_hash=image_hash,
48
+ }
45
+ algorithm='sha256')
49
+ /* Clear s0..s15 and FPSCR; TODO also VPR when MVE is implemented */
46
+ image_path = archive.extract(image_path_xz, self.workdir)
50
int i;
47
+ image_pow2ceil_expand(image_path)
51
48
+
52
for (i = 0; i < 16; i += 2) {
49
self.vm.set_console()
50
self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw',
51
'-nic', 'user',
52
@@ -XXX,XX +XXX,XX @@ def do_test_arm_orangepi_uboot_armbian(self, image_path):
53
'to <orangepipc>')
54
self.wait_for_console_pattern('Starting Load Kernel Modules...')
55
56
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
57
- 'Test artifacts fetched from unreliable apt.armbian.com')
58
- @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
59
- @skipUnless(P7ZIP_AVAILABLE, '7z not installed')
60
- def test_arm_orangepi_bionic_19_11(self):
61
- """
62
- :avocado: tags=arch:arm
63
- :avocado: tags=machine:orangepi-pc
64
- :avocado: tags=device:sd
65
- """
66
-
67
- # This test download a 196MB compressed image and expand it to 1GB
68
- image_url = ('https://dl.armbian.com/orangepipc/archive/'
69
- 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.7z')
70
- image_hash = '196a8ffb72b0123d92cea4a070894813d305c71e'
71
- image_path_7z = self.fetch_asset(image_url, asset_hash=image_hash)
72
- image_name = 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.img'
73
- image_path = os.path.join(self.workdir, image_name)
74
- process.run("7z e -o%s %s" % (self.workdir, image_path_7z))
75
- image_pow2ceil_expand(image_path)
76
-
77
- self.do_test_arm_orangepi_uboot_armbian(image_path)
78
-
79
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
80
- 'Test artifacts fetched from unreliable apt.armbian.com')
81
- @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
82
- def test_arm_orangepi_bionic_20_08(self):
83
- """
84
- :avocado: tags=arch:arm
85
- :avocado: tags=machine:orangepi-pc
86
- :avocado: tags=device:sd
87
- """
88
-
89
- # This test download a 275 MiB compressed image and expand it
90
- # to 1036 MiB, but the underlying filesystem is 1552 MiB...
91
- # As we expand it to 2 GiB we are safe.
92
-
93
- image_url = ('https://dl.armbian.com/orangepipc/archive/'
94
- 'Armbian_20.08.1_Orangepipc_bionic_current_5.8.5.img.xz')
95
- image_hash = ('b4d6775f5673486329e45a0586bf06b6'
96
- 'dbe792199fd182ac6b9c7bb6c7d3e6dd')
97
- image_path_xz = self.fetch_asset(image_url, asset_hash=image_hash,
98
- algorithm='sha256')
99
- image_path = archive.extract(image_path_xz, self.workdir)
100
- image_pow2ceil_expand(image_path)
101
-
102
- self.do_test_arm_orangepi_uboot_armbian(image_path)
103
-
104
@skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
105
def test_arm_orangepi_uboot_netbsd9(self):
106
"""
53
--
107
--
54
2.20.1
108
2.20.1
55
109
56
110
diff view generated by jsdifflib
1
From: Kunkun Jiang <jiangkunkun@huawei.com>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Accroding to the SMMUv3 spec, the SPAN field of Level1 Stream Table
3
Update the download URL of the Armbian 20.08 Bionic image for
4
Descriptor is 5 bits([4:0]).
4
test_arm_orangepi_bionic_20_08 of the orangepi-pc machine.
5
5
6
Fixes: 9bde7f0674f(hw/arm/smmuv3: Implement translate callback)
6
The archive.armbian.com URL contains more images and should keep stable
7
Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com>
7
for a longer period of time than dl.armbian.com.
8
Message-id: 20201124023711.1184-1-jiangkunkun@huawei.com
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
10
Acked-by: Eric Auger <eric.auger@redhat.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
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
15
---
13
hw/arm/smmuv3-internal.h | 2 +-
16
tests/acceptance/boot_linux_console.py | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
17
1 file changed, 1 insertion(+), 1 deletion(-)
15
18
16
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
19
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
17
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/smmuv3-internal.h
21
--- a/tests/acceptance/boot_linux_console.py
19
+++ b/hw/arm/smmuv3-internal.h
22
+++ b/tests/acceptance/boot_linux_console.py
20
@@ -XXX,XX +XXX,XX @@ static inline uint64_t l1std_l2ptr(STEDesc *desc)
23
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_bionic_20_08(self):
21
return hi << 32 | lo;
24
# to 1036 MiB, but the underlying filesystem is 1552 MiB...
22
}
25
# As we expand it to 2 GiB we are safe.
23
26
24
-#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 4))
27
- image_url = ('https://dl.armbian.com/orangepipc/archive/'
25
+#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 5))
28
+ image_url = ('https://archive.armbian.com/orangepipc/archive/'
26
29
'Armbian_20.08.1_Orangepipc_bionic_current_5.8.5.img.xz')
27
#endif
30
image_hash = ('b4d6775f5673486329e45a0586bf06b6'
31
'dbe792199fd182ac6b9c7bb6c7d3e6dd')
28
--
32
--
29
2.20.1
33
2.20.1
30
34
31
35
diff view generated by jsdifflib
1
In v8.1M a REVIDR register is defined, which is at address 0xe00ecfc
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
and is a read-only IMPDEF register providing implementation specific
3
minor revision information, like the v8A REVIDR_EL1. Implement this.
4
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
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-19-peter.maydell@linaro.org
8
---
18
---
9
hw/intc/armv7m_nvic.c | 5 +++++
19
tests/acceptance/boot_linux_console.py | 40 +++++++++++++-------------
10
1 file changed, 5 insertions(+)
20
tests/acceptance/replay_kernel.py | 8 +++---
21
2 files changed, 24 insertions(+), 24 deletions(-)
11
22
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
23
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
13
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/armv7m_nvic.c
25
--- a/tests/acceptance/boot_linux_console.py
15
+++ b/hw/intc/armv7m_nvic.c
26
+++ b/tests/acceptance/boot_linux_console.py
16
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
27
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_initrd(self):
17
}
28
:avocado: tags=machine:cubieboard
18
return val;
29
"""
19
}
30
deb_url = ('https://apt.armbian.com/pool/main/l/'
20
+ case 0xcfc:
31
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
21
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8_1M)) {
32
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
22
+ goto bad_offset;
33
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
23
+ }
34
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
24
+ return cpu->revidr;
35
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
25
case 0xd00: /* CPUID Base. */
36
kernel_path = self.extract_from_deb(deb_path,
26
return cpu->midr;
37
- '/boot/vmlinuz-4.20.7-sunxi')
27
case 0xd04: /* Interrupt Control State (ICSR) */
38
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb'
39
+ '/boot/vmlinuz-5.10.16-sunxi')
40
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
41
dtb_path = self.extract_from_deb(deb_path, dtb_path)
42
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
43
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
44
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_sata(self):
45
:avocado: tags=machine:cubieboard
46
"""
47
deb_url = ('https://apt.armbian.com/pool/main/l/'
48
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
49
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
50
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
51
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
52
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
53
kernel_path = self.extract_from_deb(deb_path,
54
- '/boot/vmlinuz-4.20.7-sunxi')
55
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb'
56
+ '/boot/vmlinuz-5.10.16-sunxi')
57
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
58
dtb_path = self.extract_from_deb(deb_path, dtb_path)
59
rootfs_url = ('https://github.com/groeck/linux-build-test/raw/'
60
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
61
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi(self):
62
:avocado: tags=machine:orangepi-pc
63
"""
64
deb_url = ('https://apt.armbian.com/pool/main/l/'
65
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
66
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
67
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
68
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
69
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
70
kernel_path = self.extract_from_deb(deb_path,
71
- '/boot/vmlinuz-4.20.7-sunxi')
72
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
73
+ '/boot/vmlinuz-5.10.16-sunxi')
74
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
75
dtb_path = self.extract_from_deb(deb_path, dtb_path)
76
77
self.vm.set_console()
78
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_initrd(self):
79
:avocado: tags=machine:orangepi-pc
80
"""
81
deb_url = ('https://apt.armbian.com/pool/main/l/'
82
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
83
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
84
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
85
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
86
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
87
kernel_path = self.extract_from_deb(deb_path,
88
- '/boot/vmlinuz-4.20.7-sunxi')
89
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
90
+ '/boot/vmlinuz-5.10.16-sunxi')
91
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
92
dtb_path = self.extract_from_deb(deb_path, dtb_path)
93
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
94
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
95
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_sd(self):
96
:avocado: tags=device:sd
97
"""
98
deb_url = ('https://apt.armbian.com/pool/main/l/'
99
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
100
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
101
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
102
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
103
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
104
kernel_path = self.extract_from_deb(deb_path,
105
- '/boot/vmlinuz-4.20.7-sunxi')
106
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
107
+ '/boot/vmlinuz-5.10.16-sunxi')
108
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
109
dtb_path = self.extract_from_deb(deb_path, dtb_path)
110
rootfs_url = ('http://storage.kernelci.org/images/rootfs/buildroot/'
111
'kci-2019.02/armel/base/rootfs.ext2.xz')
112
diff --git a/tests/acceptance/replay_kernel.py b/tests/acceptance/replay_kernel.py
113
index XXXXXXX..XXXXXXX 100644
114
--- a/tests/acceptance/replay_kernel.py
115
+++ b/tests/acceptance/replay_kernel.py
116
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_initrd(self):
117
:avocado: tags=machine:cubieboard
118
"""
119
deb_url = ('https://apt.armbian.com/pool/main/l/'
120
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
121
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
122
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
123
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
124
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
125
kernel_path = self.extract_from_deb(deb_path,
126
- '/boot/vmlinuz-4.20.7-sunxi')
127
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb'
128
+ '/boot/vmlinuz-5.10.16-sunxi')
129
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
130
dtb_path = self.extract_from_deb(deb_path, dtb_path)
131
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
132
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
28
--
133
--
29
2.20.1
134
2.20.1
30
135
31
136
diff view generated by jsdifflib
1
In v8.1M, vector table fetch failures don't set HFSR.FORCED (see rule
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
R_LLRP). (In previous versions of the architecture this was either
3
required or IMPDEF.)
4
2
3
Previously the ARMBIAN_ARTIFACTS_CACHED pre-condition was added to allow running
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.
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
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-18-peter.maydell@linaro.org
8
---
20
---
9
target/arm/m_helper.c | 6 +++++-
21
tests/acceptance/boot_linux_console.py | 12 ------------
10
1 file changed, 5 insertions(+), 1 deletion(-)
22
tests/acceptance/replay_kernel.py | 2 --
23
2 files changed, 14 deletions(-)
11
24
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
25
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
13
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/m_helper.c
27
--- a/tests/acceptance/boot_linux_console.py
15
+++ b/target/arm/m_helper.c
28
+++ b/tests/acceptance/boot_linux_console.py
16
@@ -XXX,XX +XXX,XX @@ load_fail:
29
@@ -XXX,XX +XXX,XX @@ def test_arm_exynos4210_initrd(self):
17
* The HardFault is Secure if BFHFNMINS is 0 (meaning that all HFs are
30
self.wait_for_console_pattern('Boot successful.')
18
* secure); otherwise it targets the same security state as the
31
# TODO user command, for now the uart is stuck
19
* underlying exception.
32
20
+ * In v8.1M HardFaults from vector table fetch fails don't set FORCED.
33
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
21
*/
34
- 'Test artifacts fetched from unreliable apt.armbian.com')
22
if (!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
35
def test_arm_cubieboard_initrd(self):
23
exc_secure = true;
36
"""
24
}
37
:avocado: tags=arch:arm
25
- env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK | R_V7M_HFSR_FORCED_MASK;
38
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_initrd(self):
26
+ env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK;
39
'system-control@1c00000')
27
+ if (!arm_feature(env, ARM_FEATURE_V8_1M)) {
40
# cubieboard's reboot is not functioning; omit reboot test.
28
+ env->v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
41
29
+ }
42
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
30
armv7m_nvic_set_pending_derived(env->nvic, ARMV7M_EXCP_HARD, exc_secure);
43
- 'Test artifacts fetched from unreliable apt.armbian.com')
31
return false;
44
def test_arm_cubieboard_sata(self):
32
}
45
"""
46
:avocado: tags=arch:arm
47
@@ -XXX,XX +XXX,XX @@ def test_arm_quanta_gsj_initrd(self):
48
self.wait_for_console_pattern(
49
'Give root password for system maintenance')
50
51
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
52
- 'Test artifacts fetched from unreliable apt.armbian.com')
53
def test_arm_orangepi(self):
54
"""
55
:avocado: tags=arch:arm
56
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi(self):
57
console_pattern = 'Kernel command line: %s' % kernel_command_line
58
self.wait_for_console_pattern(console_pattern)
59
60
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
61
- 'Test artifacts fetched from unreliable apt.armbian.com')
62
def test_arm_orangepi_initrd(self):
63
"""
64
:avocado: tags=arch:arm
65
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_initrd(self):
66
# Wait for VM to shut down gracefully
67
self.vm.wait()
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
84
index XXXXXXX..XXXXXXX 100644
85
--- a/tests/acceptance/replay_kernel.py
86
+++ b/tests/acceptance/replay_kernel.py
87
@@ -XXX,XX +XXX,XX @@ def test_arm_virt(self):
88
self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1)
89
90
@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab')
91
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
92
- 'Test artifacts fetched from unreliable apt.armbian.com')
93
def test_arm_cubieboard_initrd(self):
94
"""
95
:avocado: tags=arch:arm
33
--
96
--
34
2.20.1
97
2.20.1
35
98
36
99
diff view generated by jsdifflib
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Trusted Firmware now supports A72 on sbsa-ref by default [1] so enable
3
If the SSECounter link is absent, we set an error message
4
it for QEMU as well. A53 was already enabled there.
4
in sse_timer_realize() but forgot to propagate this error.
5
Add the missing 'return'.
5
6
6
1. https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/7117
7
Fixes: CID 1450755 (Null pointer dereferences)
7
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
9
Message-id: 20210312001845.1562670-1-f4bug@amsat.org
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20201120141705.246690-1-marcin.juszkiewicz@linaro.org
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
12
---
14
hw/arm/sbsa-ref.c | 23 ++++++++++++++++++++---
13
hw/timer/sse-timer.c | 1 +
15
1 file changed, 20 insertions(+), 3 deletions(-)
14
1 file changed, 1 insertion(+)
16
15
17
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
16
diff --git a/hw/timer/sse-timer.c b/hw/timer/sse-timer.c
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/sbsa-ref.c
18
--- a/hw/timer/sse-timer.c
20
+++ b/hw/arm/sbsa-ref.c
19
+++ b/hw/timer/sse-timer.c
21
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
20
@@ -XXX,XX +XXX,XX @@ static void sse_timer_realize(DeviceState *dev, Error **errp)
22
[SBSA_GWDT] = 16,
21
23
};
22
if (!s->counter) {
24
23
error_setg(errp, "counter property was not set");
25
+static const char * const valid_cpus[] = {
24
+ return;
26
+ ARM_CPU_TYPE_NAME("cortex-a53"),
27
+ ARM_CPU_TYPE_NAME("cortex-a57"),
28
+ ARM_CPU_TYPE_NAME("cortex-a72"),
29
+};
30
+
31
+static bool cpu_type_valid(const char *cpu)
32
+{
33
+ int i;
34
+
35
+ for (i = 0; i < ARRAY_SIZE(valid_cpus); i++) {
36
+ if (strcmp(cpu, valid_cpus[i]) == 0) {
37
+ return true;
38
+ }
39
+ }
40
+ return false;
41
+}
42
+
43
static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx)
44
{
45
uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;
46
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
47
const CPUArchIdList *possible_cpus;
48
int n, sbsa_max_cpus;
49
50
- if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a57"))) {
51
- error_report("sbsa-ref: CPU type other than the built-in "
52
- "cortex-a57 not supported");
53
+ if (!cpu_type_valid(machine->cpu_type)) {
54
+ error_report("mach-virt: CPU type %s not supported", machine->cpu_type);
55
exit(1);
56
}
25
}
57
26
27
s->counter_notifier.notify = sse_timer_counter_callback;
58
--
28
--
59
2.20.1
29
2.20.1
60
30
61
31
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Andrew Jones <drjones@redhat.com>
2
2
3
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
3
Prior to commit f2ce39b4f067 a MachineClass kvm_type method
4
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
4
only needed to be registered to ensure it would be executed.
5
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
5
With commit f2ce39b4f067 a kvm-type machine property must also
6
Message-id: 1605728926-352690-5-git-send-email-fnu.vikram@xilinx.com
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
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
16
---
9
MAINTAINERS | 8 ++++++++
17
include/hw/boards.h | 1 +
10
1 file changed, 8 insertions(+)
18
accel/kvm/kvm-all.c | 2 ++
19
2 files changed, 3 insertions(+)
11
20
12
diff --git a/MAINTAINERS b/MAINTAINERS
21
diff --git a/include/hw/boards.h b/include/hw/boards.h
13
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
14
--- a/MAINTAINERS
23
--- a/include/hw/boards.h
15
+++ b/MAINTAINERS
24
+++ b/include/hw/boards.h
16
@@ -XXX,XX +XXX,XX @@ F: hw/net/opencores_eth.c
25
@@ -XXX,XX +XXX,XX @@ typedef struct {
17
26
* @kvm_type:
18
Devices
27
* Return the type of KVM corresponding to the kvm-type string option or
19
-------
28
* computed based on other criteria such as the host kernel capabilities.
20
+Xilinx CAN
29
+ * kvm-type may be NULL if it is not needed.
21
+M: Vikram Garhwal <fnu.vikram@xilinx.com>
30
* @numa_mem_supported:
22
+M: Francisco Iglesias <francisco.iglesias@xilinx.com>
31
* true if '--numa node.mem' option is supported and false otherwise
23
+S: Maintained
32
* @smp_parse:
24
+F: hw/net/can/xlnx-*
33
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
25
+F: include/hw/net/xlnx-*
34
index XXXXXXX..XXXXXXX 100644
26
+F: tests/qtest/xlnx-can-test*
35
--- a/accel/kvm/kvm-all.c
27
+
36
+++ b/accel/kvm/kvm-all.c
28
EDU
37
@@ -XXX,XX +XXX,XX @@ static int kvm_init(MachineState *ms)
29
M: Jiri Slaby <jslaby@suse.cz>
38
"kvm-type",
30
S: Maintained
39
&error_abort);
40
type = mc->kvm_type(ms, kvm_type);
41
+ } else if (mc->kvm_type) {
42
+ type = mc->kvm_type(ms, NULL);
43
}
44
45
do {
31
--
46
--
32
2.20.1
47
2.20.1
33
48
34
49
diff view generated by jsdifflib
1
The RAS feature has a block of memory-mapped registers at offset
1
From: Andrew Jones <drjones@redhat.com>
2
0x5000 within the PPB. For a "minimal RAS" implementation we provide
3
no error records and so the only registers that exist in the block
4
are ERRIIDR and ERRDEVID.
5
2
6
The "RAZ/WI for privileged, BusFault for nonprivileged" behaviour
3
The virt machine already checks KVM_CAP_ARM_VM_IPA_SIZE to get the
7
of the "nvic-default" region is actually valid for minimal-RAS,
4
upper bound of the IPA size. If that bound is lower than the highest
8
so the main benefit of providing an explicit implementation of
5
possible GPA for the machine, then QEMU will error out. However, the
9
the register block is more accurate LOG_UNIMP messages, and a
6
IPA is set to 40 when the highest GPA is less than or equal to 40,
10
framework for where we could add a real RAS implementation later
7
even when KVM may support an IPA limit as low as 32. This means KVM
11
if necessary.
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.
12
14
15
Suggested-by: Marc Zyngier <maz@kernel.org>
16
Signed-off-by: Andrew Jones <drjones@redhat.com>
17
Reviewed-by: Eric Auger <eric.auger@redhat.com>
18
Reviewed-by: Marc Zyngier <maz@kernel.org>
19
Message-id: 20210310135218.255205-3-drjones@redhat.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20201119215617.29887-27-peter.maydell@linaro.org
16
---
21
---
17
include/hw/intc/armv7m_nvic.h | 1 +
22
target/arm/kvm_arm.h | 6 ++++--
18
hw/intc/armv7m_nvic.c | 56 +++++++++++++++++++++++++++++++++++
23
hw/arm/virt.c | 23 ++++++++++++++++-------
19
2 files changed, 57 insertions(+)
24
target/arm/kvm.c | 4 +++-
25
3 files changed, 23 insertions(+), 10 deletions(-)
20
26
21
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
27
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
22
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/intc/armv7m_nvic.h
29
--- a/target/arm/kvm_arm.h
24
+++ b/include/hw/intc/armv7m_nvic.h
30
+++ b/target/arm/kvm_arm.h
25
@@ -XXX,XX +XXX,XX @@ struct NVICState {
31
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_sve_supported(void);
26
MemoryRegion sysreg_ns_mem;
32
/**
27
MemoryRegion systickmem;
33
* kvm_arm_get_max_vm_ipa_size:
28
MemoryRegion systick_ns_mem;
34
* @ms: Machine state handle
29
+ MemoryRegion ras_mem;
35
+ * @fixed_ipa: True when the IPA limit is fixed at 40. This is the case
30
MemoryRegion container;
36
+ * for legacy KVM.
31
MemoryRegion defaultmem;
37
*
32
38
* Returns the number of bits in the IPA address space supported by KVM
33
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
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
34
index XXXXXXX..XXXXXXX 100644
55
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/intc/armv7m_nvic.c
56
--- a/hw/arm/virt.c
36
+++ b/hw/intc/armv7m_nvic.c
57
+++ b/hw/arm/virt.c
37
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
58
@@ -XXX,XX +XXX,XX @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
38
.endianness = DEVICE_NATIVE_ENDIAN,
59
static int virt_kvm_type(MachineState *ms, const char *type_str)
39
};
60
{
40
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;
41
+
66
+
42
+static MemTxResult ras_read(void *opaque, hwaddr addr,
67
+ max_vm_pa_size = kvm_arm_get_max_vm_ipa_size(ms, &fixed_ipa);
43
+ uint64_t *data, unsigned size,
68
44
+ MemTxAttrs attrs)
69
/* we freeze the memory map to compute the highest gpa */
45
+{
70
virt_set_memmap(vms);
46
+ if (attrs.user) {
71
47
+ return MEMTX_ERROR;
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;
48
+ }
79
+ }
49
+
80
+
50
+ switch (addr) {
81
if (requested_pa_size > max_vm_pa_size) {
51
+ case 0xe10: /* ERRIIDR */
82
error_report("-m and ,maxmem option values "
52
+ /* architect field = Arm; product/variant/revision 0 */
83
"require an IPA range (%d bits) larger than "
53
+ *data = 0x43b;
84
"the one supported by the host (%d bits)",
54
+ break;
85
requested_pa_size, max_vm_pa_size);
55
+ case 0xfc8: /* ERRDEVID */
86
- exit(1);
56
+ /* Minimal RAS: we implement 0 error record indexes */
87
+ exit(1);
57
+ *data = 0;
88
}
58
+ break;
89
/*
59
+ default:
90
- * By default we return 0 which corresponds to an implicit legacy
60
+ qemu_log_mask(LOG_UNIMP, "Read RAS register offset 0x%x\n",
91
- * 40b IPA setting. Otherwise we return the actual requested PA
61
+ (uint32_t)addr);
92
- * logsize
62
+ *data = 0;
93
+ * We return the requested PA log size, unless KVM only supports
63
+ break;
94
+ * the implicit legacy 40b IPA setting, in which case the kvm_type
64
+ }
95
+ * must be 0.
65
+ return MEMTX_OK;
96
*/
66
+}
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
103
index XXXXXXX..XXXXXXX 100644
104
--- a/target/arm/kvm.c
105
+++ b/target/arm/kvm.c
106
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_pmu_supported(void)
107
return kvm_check_extension(kvm_state, KVM_CAP_ARM_PMU_V3);
108
}
109
110
-int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
111
+int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa)
112
{
113
KVMState *s = KVM_STATE(ms->accelerator);
114
int ret;
115
116
ret = kvm_check_extension(s, KVM_CAP_ARM_VM_IPA_SIZE);
117
+ *fixed_ipa = ret <= 0;
67
+
118
+
68
+static MemTxResult ras_write(void *opaque, hwaddr addr,
119
return ret > 0 ? ret : 40;
69
+ uint64_t value, unsigned size,
70
+ MemTxAttrs attrs)
71
+{
72
+ if (attrs.user) {
73
+ return MEMTX_ERROR;
74
+ }
75
+
76
+ switch (addr) {
77
+ default:
78
+ qemu_log_mask(LOG_UNIMP, "Write to RAS register offset 0x%x\n",
79
+ (uint32_t)addr);
80
+ break;
81
+ }
82
+ return MEMTX_OK;
83
+}
84
+
85
+static const MemoryRegionOps ras_ops = {
86
+ .read_with_attrs = ras_read,
87
+ .write_with_attrs = ras_write,
88
+ .endianness = DEVICE_NATIVE_ENDIAN,
89
+};
90
+
91
/*
92
* Unassigned portions of the PPB space are RAZ/WI for privileged
93
* accesses, and fault for non-privileged accesses.
94
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
95
&s->systick_ns_mem, 1);
96
}
97
98
+ if (cpu_isar_feature(aa32_ras, s->cpu)) {
99
+ memory_region_init_io(&s->ras_mem, OBJECT(s),
100
+ &ras_ops, s, "nvic_ras", 0x1000);
101
+ memory_region_add_subregion(&s->container, 0x5000, &s->ras_mem);
102
+ }
103
+
104
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);
105
}
120
}
106
121
107
--
122
--
108
2.20.1
123
2.20.1
109
124
110
125
diff view generated by jsdifflib
1
The constant-expander functions like negate, plus_2, etc, are
1
From: Hao Wu <wuhaotsh@google.com>
2
generally useful; move them up in translate.c so we can use them in
3
the VFP/Neon decoders as well as in the A32/T32/T16 decoders.
4
2
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>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Message-id: 20210311180855.149764-2-wuhaotsh@google.com
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-9-peter.maydell@linaro.org
8
---
15
---
9
target/arm/translate.c | 46 +++++++++++++++++++++++-------------------
16
include/hw/misc/npcm7xx_pwm.h | 4 +++-
10
1 file changed, 25 insertions(+), 21 deletions(-)
17
hw/misc/npcm7xx_pwm.c | 4 ++++
18
2 files changed, 7 insertions(+), 1 deletion(-)
11
19
12
diff --git a/target/arm/translate.c b/target/arm/translate.c
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/target/arm/translate.c
22
--- a/include/hw/misc/npcm7xx_pwm.h
15
+++ b/target/arm/translate.c
23
+++ b/include/hw/misc/npcm7xx_pwm.h
16
@@ -XXX,XX +XXX,XX @@ static void arm_gen_condlabel(DisasContext *s)
24
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxPWM {
25
* @iomem: Memory region through which registers are accessed.
26
* @clock: The PWM clock.
27
* @pwm: The PWM channels owned by this module.
28
+ * @duty_gpio_out: The duty cycle of each PWM channels as a output GPIO.
29
* @ppr: The prescaler register.
30
* @csr: The clock selector register.
31
* @pcr: The control register.
32
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxPWMState {
33
MemoryRegion iomem;
34
35
Clock *clock;
36
- NPCM7xxPWM pwm[NPCM7XX_PWM_PER_MODULE];
37
+ NPCM7xxPWM pwm[NPCM7XX_PWM_PER_MODULE];
38
+ qemu_irq duty_gpio_out[NPCM7XX_PWM_PER_MODULE];
39
40
uint32_t ppr;
41
uint32_t csr;
42
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/misc/npcm7xx_pwm.c
45
+++ b/hw/misc/npcm7xx_pwm.c
46
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_update_duty(NPCM7xxPWM *p)
47
trace_npcm7xx_pwm_update_duty(DEVICE(p->module)->canonical_path,
48
p->index, p->duty, duty);
49
p->duty = duty;
50
+ qemu_set_irq(p->module->duty_gpio_out[p->index], p->duty);
17
}
51
}
18
}
52
}
19
53
20
+/*
54
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_init(Object *obj)
21
+ * Constant expanders for the decoders.
55
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
22
+ */
56
int i;
23
+
57
24
+static int negate(DisasContext *s, int x)
58
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->pwm) != NPCM7XX_PWM_PER_MODULE);
25
+{
59
for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
26
+ return -x;
60
NPCM7xxPWM *p = &s->pwm[i];
27
+}
61
p->module = s;
28
+
62
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_init(Object *obj)
29
+static int plus_2(DisasContext *s, int x)
63
object_property_add_uint32_ptr(obj, "duty[*]",
30
+{
64
&s->pwm[i].duty, OBJ_PROP_FLAG_READ);
31
+ return x + 2;
65
}
32
+}
66
+ qdev_init_gpio_out_named(DEVICE(s), s->duty_gpio_out,
33
+
67
+ "duty-gpio-out", NPCM7XX_PWM_PER_MODULE);
34
+static int times_2(DisasContext *s, int x)
68
}
35
+{
69
36
+ return x * 2;
70
static const VMStateDescription vmstate_npcm7xx_pwm = {
37
+}
38
+
39
+static int times_4(DisasContext *s, int x)
40
+{
41
+ return x * 4;
42
+}
43
+
44
/* Flags for the disas_set_da_iss info argument:
45
* lower bits hold the Rt register number, higher bits are flags.
46
*/
47
@@ -XXX,XX +XXX,XX @@ static void arm_skip_unless(DisasContext *s, uint32_t cond)
48
49
50
/*
51
- * Constant expanders for the decoders.
52
+ * Constant expanders used by T16/T32 decode
53
*/
54
55
-static int negate(DisasContext *s, int x)
56
-{
57
- return -x;
58
-}
59
-
60
-static int plus_2(DisasContext *s, int x)
61
-{
62
- return x + 2;
63
-}
64
-
65
-static int times_2(DisasContext *s, int x)
66
-{
67
- return x * 2;
68
-}
69
-
70
-static int times_4(DisasContext *s, int x)
71
-{
72
- return x * 4;
73
-}
74
-
75
/* Return only the rotation part of T32ExpandImm. */
76
static int t32_expandimm_rot(DisasContext *s, int x)
77
{
78
--
71
--
79
2.20.1
72
2.20.1
80
73
81
74
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
The QTests perform five tests on the Xilinx ZynqMP CAN controller:
3
This patch implements Multi Function Timer (MFT) module for NPCM7XX.
4
Tests the CAN controller in loopback, sleep and snoop mode.
4
This module is mainly used to configure PWM fans. It has just enough
5
Tests filtering of incoming CAN messages.
5
functionality to make the PWM fan kernel module work.
6
6
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
The module takes two input, the max_rpm of a fan (modifiable via QMP)
8
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
8
and duty cycle (a GPIO from the PWM module.) The actual measured RPM
9
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
9
is equal to max_rpm * duty_cycle / NPCM7XX_PWM_MAX_DUTY. The RPM is
10
Message-id: 1605728926-352690-4-git-send-email-fnu.vikram@xilinx.com
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>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
22
---
13
tests/qtest/xlnx-can-test.c | 360 ++++++++++++++++++++++++++++++++++++
23
include/hw/misc/npcm7xx_mft.h | 70 +++++
14
tests/qtest/meson.build | 1 +
24
hw/misc/npcm7xx_mft.c | 540 ++++++++++++++++++++++++++++++++++
15
2 files changed, 361 insertions(+)
25
hw/misc/meson.build | 1 +
16
create mode 100644 tests/qtest/xlnx-can-test.c
26
hw/misc/trace-events | 8 +
27
4 files changed, 619 insertions(+)
28
create mode 100644 include/hw/misc/npcm7xx_mft.h
29
create mode 100644 hw/misc/npcm7xx_mft.c
17
30
18
diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c
31
diff --git a/include/hw/misc/npcm7xx_mft.h b/include/hw/misc/npcm7xx_mft.h
19
new file mode 100644
32
new file mode 100644
20
index XXXXXXX..XXXXXXX
33
index XXXXXXX..XXXXXXX
21
--- /dev/null
34
--- /dev/null
22
+++ b/tests/qtest/xlnx-can-test.c
35
+++ b/include/hw/misc/npcm7xx_mft.h
23
@@ -XXX,XX +XXX,XX @@
36
@@ -XXX,XX +XXX,XX @@
24
+/*
37
+/*
25
+ * QTests for the Xilinx ZynqMP CAN controller.
38
+ * Nuvoton NPCM7xx MFT Module
26
+ *
39
+ *
27
+ * Copyright (c) 2020 Xilinx Inc.
40
+ * Copyright 2021 Google LLC
28
+ *
41
+ *
29
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
42
+ * This program is free software; you can redistribute it and/or modify it
43
+ * under the terms of the GNU General Public License as published by the
44
+ * Free Software Foundation; either version 2 of the License, or
45
+ * (at your option) any later version.
30
+ *
46
+ *
31
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
47
+ * This program is distributed in the hope that it will be useful, but WITHOUT
32
+ * of this software and associated documentation files (the "Software"), to deal
48
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
33
+ * in the Software without restriction, including without limitation the rights
49
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
34
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
50
+ * for more details.
35
+ * copies of the Software, and to permit persons to whom the Software is
51
+ */
36
+ * furnished to do so, subject to the following conditions:
52
+#ifndef NPCM7XX_MFT_H
53
+#define NPCM7XX_MFT_H
54
+
55
+#include "exec/memory.h"
56
+#include "hw/clock.h"
57
+#include "hw/irq.h"
58
+#include "hw/sysbus.h"
59
+#include "qom/object.h"
60
+
61
+/* Max Fan input number. */
62
+#define NPCM7XX_MFT_MAX_FAN_INPUT 19
63
+
64
+/*
65
+ * Number of registers in one MFT module. Don't change this without increasing
66
+ * the version_id in vmstate.
67
+ */
68
+#define NPCM7XX_MFT_NR_REGS (0x20 / sizeof(uint16_t))
69
+
70
+/*
71
+ * The MFT can take up to 4 inputs: A0, B0, A1, B1. It can measure one A and one
72
+ * B simultaneously. NPCM7XX_MFT_INASEL and NPCM7XX_MFT_INBSEL are used to
73
+ * select which A or B input are used.
74
+ */
75
+#define NPCM7XX_MFT_FANIN_COUNT 4
76
+
77
+/**
78
+ * struct NPCM7xxMFTState - Multi Functional Tachometer device state.
79
+ * @parent: System bus device.
80
+ * @iomem: Memory region through which registers are accessed.
81
+ * @clock_in: The input clock for MFT from CLK module.
82
+ * @clock_{1,2}: The counter clocks for NPCM7XX_MFT_CNT{1,2}
83
+ * @irq: The IRQ for this MFT state.
84
+ * @regs: The MMIO registers.
85
+ * @max_rpm: The maximum rpm for fans. Order: A0, B0, A1, B1.
86
+ * @duty: The duty cycles for fans, relative to NPCM7XX_PWM_MAX_DUTY.
87
+ */
88
+typedef struct NPCM7xxMFTState {
89
+ SysBusDevice parent;
90
+
91
+ MemoryRegion iomem;
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
108
new file mode 100644
109
index XXXXXXX..XXXXXXX
110
--- /dev/null
111
+++ b/hw/misc/npcm7xx_mft.c
112
@@ -XXX,XX +XXX,XX @@
113
+/*
114
+ * Nuvoton NPCM7xx MFT Module
37
+ *
115
+ *
38
+ * The above copyright notice and this permission notice shall be included in
116
+ * Copyright 2021 Google LLC
39
+ * all copies or substantial portions of the Software.
40
+ *
117
+ *
41
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
118
+ * This program is free software; you can redistribute it and/or modify it
42
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
119
+ * under the terms of the GNU General Public License as published by the
43
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
120
+ * Free Software Foundation; either version 2 of the License, or
44
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
121
+ * (at your option) any later version.
45
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
122
+ *
46
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
123
+ * This program is distributed in the hope that it will be useful, but WITHOUT
47
+ * THE SOFTWARE.
124
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
125
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
126
+ * for more details.
48
+ */
127
+ */
49
+
128
+
50
+#include "qemu/osdep.h"
129
+#include "qemu/osdep.h"
51
+#include "libqos/libqtest.h"
130
+#include "hw/irq.h"
52
+
131
+#include "hw/qdev-clock.h"
53
+/* Base address. */
132
+#include "hw/qdev-properties.h"
54
+#define CAN0_BASE_ADDR 0xFF060000
133
+#include "hw/misc/npcm7xx_mft.h"
55
+#define CAN1_BASE_ADDR 0xFF070000
134
+#include "hw/misc/npcm7xx_pwm.h"
56
+
135
+#include "hw/registerfields.h"
57
+/* Register addresses. */
136
+#include "migration/vmstate.h"
58
+#define R_SRR_OFFSET 0x00
137
+#include "qapi/error.h"
59
+#define R_MSR_OFFSET 0x04
138
+#include "qapi/visitor.h"
60
+#define R_SR_OFFSET 0x18
139
+#include "qemu/bitops.h"
61
+#define R_ISR_OFFSET 0x1C
140
+#include "qemu/error-report.h"
62
+#define R_ICR_OFFSET 0x24
141
+#include "qemu/log.h"
63
+#define R_TXID_OFFSET 0x30
142
+#include "qemu/module.h"
64
+#define R_TXDLC_OFFSET 0x34
143
+#include "qemu/timer.h"
65
+#define R_TXDATA1_OFFSET 0x38
144
+#include "qemu/units.h"
66
+#define R_TXDATA2_OFFSET 0x3C
145
+#include "trace.h"
67
+#define R_RXID_OFFSET 0x50
146
+
68
+#define R_RXDLC_OFFSET 0x54
147
+/*
69
+#define R_RXDATA1_OFFSET 0x58
148
+ * Some of the registers can only accessed via 16-bit ops and some can only
70
+#define R_RXDATA2_OFFSET 0x5C
149
+ * be accessed via 8-bit ops. However we mark all of them using REG16 to
71
+#define R_AFR 0x60
150
+ * simplify implementation. npcm7xx_mft_check_mem_op checks the access length
72
+#define R_AFMR1 0x64
151
+ * of memory operations.
73
+#define R_AFIR1 0x68
152
+ */
74
+#define R_AFMR2 0x6C
153
+REG16(NPCM7XX_MFT_CNT1, 0x00);
75
+#define R_AFIR2 0x70
154
+REG16(NPCM7XX_MFT_CRA, 0x02);
76
+#define R_AFMR3 0x74
155
+REG16(NPCM7XX_MFT_CRB, 0x04);
77
+#define R_AFIR3 0x78
156
+REG16(NPCM7XX_MFT_CNT2, 0x06);
78
+#define R_AFMR4 0x7C
157
+REG16(NPCM7XX_MFT_PRSC, 0x08);
79
+#define R_AFIR4 0x80
158
+REG16(NPCM7XX_MFT_CKC, 0x0a);
80
+
159
+REG16(NPCM7XX_MFT_MCTRL, 0x0c);
81
+/* CAN modes. */
160
+REG16(NPCM7XX_MFT_ICTRL, 0x0e);
82
+#define CONFIG_MODE 0x00
161
+REG16(NPCM7XX_MFT_ICLR, 0x10);
83
+#define NORMAL_MODE 0x00
162
+REG16(NPCM7XX_MFT_IEN, 0x12);
84
+#define LOOPBACK_MODE 0x02
163
+REG16(NPCM7XX_MFT_CPA, 0x14);
85
+#define SNOOP_MODE 0x04
164
+REG16(NPCM7XX_MFT_CPB, 0x16);
86
+#define SLEEP_MODE 0x01
165
+REG16(NPCM7XX_MFT_CPCFG, 0x18);
87
+#define ENABLE_CAN (1 << 1)
166
+REG16(NPCM7XX_MFT_INASEL, 0x1a);
88
+#define STATUS_NORMAL_MODE (1 << 3)
167
+REG16(NPCM7XX_MFT_INBSEL, 0x1c);
89
+#define STATUS_LOOPBACK_MODE (1 << 1)
168
+
90
+#define STATUS_SNOOP_MODE (1 << 12)
169
+/* Register Fields */
91
+#define STATUS_SLEEP_MODE (1 << 2)
170
+#define NPCM7XX_MFT_CKC_C2CSEL BIT(3)
92
+#define ISR_TXOK (1 << 1)
171
+#define NPCM7XX_MFT_CKC_C1CSEL BIT(0)
93
+#define ISR_RXOK (1 << 4)
172
+
94
+
173
+#define NPCM7XX_MFT_MCTRL_TBEN BIT(6)
95
+static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_rx,
174
+#define NPCM7XX_MFT_MCTRL_TAEN BIT(5)
96
+ uint8_t can_timestamp)
175
+#define NPCM7XX_MFT_MCTRL_TBEDG BIT(4)
97
+{
176
+#define NPCM7XX_MFT_MCTRL_TAEDG BIT(3)
98
+ uint16_t size = 0;
177
+#define NPCM7XX_MFT_MCTRL_MODE5 BIT(2)
99
+ uint8_t len = 4;
178
+
100
+
179
+#define NPCM7XX_MFT_ICTRL_TFPND BIT(5)
101
+ while (size < len) {
180
+#define NPCM7XX_MFT_ICTRL_TEPND BIT(4)
102
+ if (R_RXID_OFFSET + 4 * size == R_RXDLC_OFFSET) {
181
+#define NPCM7XX_MFT_ICTRL_TDPND BIT(3)
103
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size] + can_timestamp);
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
+{
227
+ int i;
228
+
229
+ /* Only registers PRSC ~ INBSEL need to be reset. */
230
+ for (i = R_NPCM7XX_MFT_PRSC; i <= R_NPCM7XX_MFT_INBSEL; ++i) {
231
+ s->regs[i] = 0;
232
+ }
233
+}
234
+
235
+static void npcm7xx_mft_clear_interrupt(NPCM7xxMFTState *s, uint8_t iclr)
236
+{
237
+ /*
238
+ * Clear bits in ICTRL where corresponding bits in iclr is 1.
239
+ * Both iclr and ictrl are 8-bit regs. (See npcm7xx_mft_check_mem_op)
240
+ */
241
+ s->regs[R_NPCM7XX_MFT_ICTRL] &= ~iclr;
242
+}
243
+
244
+/*
245
+ * If the CPCFG's condition should be triggered during count down from
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;
104
+ } else {
302
+ } else {
105
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
303
+ state = NPCM7XX_CAPTURE_SUCCEED;
106
+ }
304
+ }
107
+
305
+ } else {
108
+ size++;
306
+ count = stopped;
109
+ }
307
+ state = NPCM7XX_CAPTURE_COMPARE_HIT;
110
+}
308
+ }
111
+
309
+
112
+static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx)
310
+ if (count != -1) {
113
+{
311
+ *cnt = count;
114
+ uint32_t int_status;
312
+ }
115
+
313
+ trace_npcm7xx_mft_rpm(clock->canonical_path, clock_get_hz(clock),
116
+ /* Read the interrupt on CAN rx. */
314
+ state, count, rpm, duty);
117
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
315
+ return state;
118
+
119
+ g_assert_cmpint(int_status, ==, ISR_RXOK);
120
+
121
+ /* Read the RX register data for CAN. */
122
+ buf_rx[0] = qtest_readl(qts, can_base_addr + R_RXID_OFFSET);
123
+ buf_rx[1] = qtest_readl(qts, can_base_addr + R_RXDLC_OFFSET);
124
+ buf_rx[2] = qtest_readl(qts, can_base_addr + R_RXDATA1_OFFSET);
125
+ buf_rx[3] = qtest_readl(qts, can_base_addr + R_RXDATA2_OFFSET);
126
+
127
+ /* Clear the RX interrupt. */
128
+ qtest_writel(qts, CAN1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK);
129
+}
130
+
131
+static void send_data(QTestState *qts, uint64_t can_base_addr,
132
+ const uint32_t *buf_tx)
133
+{
134
+ uint32_t int_status;
135
+
136
+ /* Write the TX register data for CAN. */
137
+ qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]);
138
+ qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]);
139
+ qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]);
140
+ qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]);
141
+
142
+ /* Read the interrupt on CAN for tx. */
143
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK;
144
+
145
+ g_assert_cmpint(int_status, ==, ISR_TXOK);
146
+
147
+ /* Clear the interrupt for tx. */
148
+ qtest_writel(qts, CAN0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK);
149
+}
316
+}
150
+
317
+
151
+/*
318
+/*
152
+ * This test will be transferring data from CAN0 and CAN1 through canbus. CAN0
319
+ * Capture Fan RPM and update CNT and CR registers accordingly.
153
+ * initiate the data transfer to can-bus, CAN1 receives the data. Test compares
320
+ * Raise IRQ if certain contidions are met in IEN.
154
+ * the data sent from CAN0 with received on CAN1.
321
+ */
155
+ */
322
+static void npcm7xx_mft_capture(NPCM7xxMFTState *s)
156
+static void test_can_bus(void)
323
+{
157
+{
324
+ int irq_level = 0;
158
+ const uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
325
+ NPCM7xxMFTCaptureState state;
159
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
326
+ int sel;
160
+ uint32_t status = 0;
327
+ uint8_t cpcfg;
161
+ uint8_t can_timestamp = 1;
162
+
163
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
164
+ " -object can-bus,id=canbus0"
165
+ " -machine xlnx-zcu102.canbus0=canbus0"
166
+ " -machine xlnx-zcu102.canbus1=canbus0"
167
+ );
168
+
169
+ /* Configure the CAN0 and CAN1. */
170
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
171
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
172
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
173
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
174
+
175
+ /* Check here if CAN0 and CAN1 are in normal mode. */
176
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
177
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
178
+
179
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
180
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
181
+
182
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
183
+
184
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
185
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
186
+
187
+ qtest_quit(qts);
188
+}
189
+
190
+/*
191
+ * This test is performing loopback mode on CAN0 and CAN1. Data sent from TX of
192
+ * each CAN0 and CAN1 are compared with RX register data for respective CAN.
193
+ */
194
+static void test_can_loopback(void)
195
+{
196
+ uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
197
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
198
+ uint32_t status = 0;
199
+
200
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
201
+ " -object can-bus,id=canbus0"
202
+ " -machine xlnx-zcu102.canbus0=canbus0"
203
+ " -machine xlnx-zcu102.canbus1=canbus0"
204
+ );
205
+
206
+ /* Configure the CAN0 in loopback mode. */
207
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
208
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
209
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
210
+
211
+ /* Check here if CAN0 is set in loopback mode. */
212
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
213
+
214
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
215
+
216
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
217
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
218
+ match_rx_tx_data(buf_tx, buf_rx, 0);
219
+
220
+ /* Configure the CAN1 in loopback mode. */
221
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
222
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
223
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
224
+
225
+ /* Check here if CAN1 is set in loopback mode. */
226
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
227
+
228
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
229
+
230
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
231
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
232
+ match_rx_tx_data(buf_tx, buf_rx, 0);
233
+
234
+ qtest_quit(qts);
235
+}
236
+
237
+/*
238
+ * Enable filters for CAN1. This will filter incoming messages with ID. In this
239
+ * test message will pass through filter 2.
240
+ */
241
+static void test_can_filter(void)
242
+{
243
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
244
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
245
+ uint32_t status = 0;
246
+ uint8_t can_timestamp = 1;
247
+
248
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
249
+ " -object can-bus,id=canbus0"
250
+ " -machine xlnx-zcu102.canbus0=canbus0"
251
+ " -machine xlnx-zcu102.canbus1=canbus0"
252
+ );
253
+
254
+ /* Configure the CAN0 and CAN1. */
255
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
256
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
257
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
258
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
259
+
260
+ /* Check here if CAN0 and CAN1 are in normal mode. */
261
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
262
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
263
+
264
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
265
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
266
+
267
+ /* Set filter for CAN1 for incoming messages. */
268
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0x0);
269
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR1, 0xF7);
270
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR1, 0x121F);
271
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR2, 0x5431);
272
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR2, 0x14);
273
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR3, 0x1234);
274
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR3, 0x5431);
275
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR4, 0xFFF);
276
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR4, 0x1234);
277
+
278
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0xF);
279
+
280
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
281
+
282
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
283
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
284
+
285
+ qtest_quit(qts);
286
+}
287
+
288
+/* Testing sleep mode on CAN0 while CAN1 is in normal mode. */
289
+static void test_can_sleepmode(void)
290
+{
291
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
292
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
293
+ uint32_t status = 0;
294
+ uint8_t can_timestamp = 1;
295
+
296
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
297
+ " -object can-bus,id=canbus0"
298
+ " -machine xlnx-zcu102.canbus0=canbus0"
299
+ " -machine xlnx-zcu102.canbus1=canbus0"
300
+ );
301
+
302
+ /* Configure the CAN0. */
303
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
304
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SLEEP_MODE);
305
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
306
+
307
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
308
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
309
+
310
+ /* Check here if CAN0 is in SLEEP mode and CAN1 in normal mode. */
311
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
312
+ g_assert_cmpint(status, ==, STATUS_SLEEP_MODE);
313
+
314
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
315
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
316
+
317
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
318
+
328
+
319
+ /*
329
+ /*
320
+ * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode.
330
+ * If not mode 5, the behavior is undefined. We just do nothing in this
321
+ * Check the CAN0 status now. It should exit the sleep mode and receive the
331
+ * case.
322
+ * incoming data.
323
+ */
332
+ */
324
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
333
+ if (!(s->regs[R_NPCM7XX_MFT_MCTRL] & NPCM7XX_MFT_MCTRL_MODE5)) {
325
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
334
+ return;
326
+
335
+ }
327
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
336
+
328
+
337
+ /* Capture input A. */
329
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
338
+ if (s->regs[R_NPCM7XX_MFT_MCTRL] & NPCM7XX_MFT_MCTRL_TAEN &&
330
+
339
+ s->regs[R_NPCM7XX_MFT_CKC] & NPCM7XX_MFT_CKC_C1CSEL) {
331
+ qtest_quit(qts);
340
+ sel = s->regs[R_NPCM7XX_MFT_INASEL] & NPCM7XX_MFT_INASEL_SELA;
332
+}
341
+ cpcfg = NPCM7XX_MFT_CPCFG_GET_A(s->regs[R_NPCM7XX_MFT_CPCFG]);
333
+
342
+ state = npcm7xx_mft_compute_cnt(s->clock_1,
334
+/* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */
343
+ sel ? s->max_rpm[2] : s->max_rpm[0],
335
+static void test_can_snoopmode(void)
344
+ sel ? s->duty[2] : s->duty[0],
336
+{
345
+ s->regs[R_NPCM7XX_MFT_CPA],
337
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
346
+ cpcfg,
338
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
347
+ &s->regs[R_NPCM7XX_MFT_CNT1]);
339
+ uint32_t status = 0;
348
+ switch (state) {
340
+ uint8_t can_timestamp = 1;
349
+ case NPCM7XX_CAPTURE_SUCCEED:
341
+
350
+ /* Interrupt on input capture on TAn transition - TAPND */
342
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
351
+ s->regs[R_NPCM7XX_MFT_CRA] = s->regs[R_NPCM7XX_MFT_CNT1];
343
+ " -object can-bus,id=canbus0"
352
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TAPND;
344
+ " -machine xlnx-zcu102.canbus0=canbus0"
353
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TAIEN) {
345
+ " -machine xlnx-zcu102.canbus1=canbus0"
354
+ irq_level = 1;
346
+ );
355
+ }
347
+
356
+ break;
348
+ /* Configure the CAN0. */
357
+
349
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
358
+ case NPCM7XX_CAPTURE_COMPARE_HIT:
350
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SNOOP_MODE);
359
+ /* Compare Hit - TEPND */
351
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
360
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TEPND;
352
+
361
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TEIEN) {
353
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
362
+ irq_level = 1;
354
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
363
+ }
355
+
364
+ break;
356
+ /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */
365
+
357
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
366
+ case NPCM7XX_CAPTURE_UNDERFLOW:
358
+ g_assert_cmpint(status, ==, STATUS_SNOOP_MODE);
367
+ /* Underflow - TCPND */
359
+
368
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TCPND;
360
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
369
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TCIEN) {
361
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
370
+ irq_level = 1;
362
+
371
+ }
363
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
372
+ break;
364
+
373
+
365
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
374
+ default:
366
+
375
+ g_assert_not_reached();
367
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
376
+ }
368
+
377
+ }
369
+ qtest_quit(qts);
378
+
370
+}
379
+ /* Capture input B. */
371
+
380
+ if (s->regs[R_NPCM7XX_MFT_MCTRL] & NPCM7XX_MFT_MCTRL_TBEN &&
372
+int main(int argc, char **argv)
381
+ s->regs[R_NPCM7XX_MFT_CKC] & NPCM7XX_MFT_CKC_C2CSEL) {
373
+{
382
+ sel = s->regs[R_NPCM7XX_MFT_INBSEL] & NPCM7XX_MFT_INBSEL_SELB;
374
+ g_test_init(&argc, &argv, NULL);
383
+ cpcfg = NPCM7XX_MFT_CPCFG_GET_B(s->regs[R_NPCM7XX_MFT_CPCFG]);
375
+
384
+ state = npcm7xx_mft_compute_cnt(s->clock_2,
376
+ qtest_add_func("/net/can/can_bus", test_can_bus);
385
+ sel ? s->max_rpm[3] : s->max_rpm[1],
377
+ qtest_add_func("/net/can/can_loopback", test_can_loopback);
386
+ sel ? s->duty[3] : s->duty[1],
378
+ qtest_add_func("/net/can/can_filter", test_can_filter);
387
+ s->regs[R_NPCM7XX_MFT_CPB],
379
+ qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode);
388
+ cpcfg,
380
+ qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode);
389
+ &s->regs[R_NPCM7XX_MFT_CNT2]);
381
+
390
+ switch (state) {
382
+ return g_test_run();
391
+ case NPCM7XX_CAPTURE_SUCCEED:
383
+}
392
+ /* Interrupt on input capture on TBn transition - TBPND */
384
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
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
+ },
573
+};
574
+
575
+static void npcm7xx_mft_enter_reset(Object *obj, ResetType type)
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);
632
+ DeviceClass *dc = DEVICE_CLASS(klass);
633
+
634
+ dc->desc = "NPCM7xx MFT Controller";
635
+ dc->vmsd = &vmstate_npcm7xx_mft;
636
+ rc->phases.enter = npcm7xx_mft_enter_reset;
637
+ rc->phases.hold = npcm7xx_mft_hold_reset;
638
+}
639
+
640
+static const TypeInfo npcm7xx_mft_info = {
641
+ .name = TYPE_NPCM7XX_MFT,
642
+ .parent = TYPE_SYS_BUS_DEVICE,
643
+ .instance_size = sizeof(NPCM7xxMFTState),
644
+ .class_init = npcm7xx_mft_class_init,
645
+ .instance_init = npcm7xx_mft_init,
646
+};
647
+
648
+static void npcm7xx_mft_register_type(void)
649
+{
650
+ type_register_static(&npcm7xx_mft_info);
651
+}
652
+type_init(npcm7xx_mft_register_type);
653
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
385
index XXXXXXX..XXXXXXX 100644
654
index XXXXXXX..XXXXXXX 100644
386
--- a/tests/qtest/meson.build
655
--- a/hw/misc/meson.build
387
+++ b/tests/qtest/meson.build
656
+++ b/hw/misc/meson.build
388
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
657
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
389
['arm-cpu-features',
658
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
390
'numa-test',
659
'npcm7xx_clk.c',
391
'boot-serial-test',
660
'npcm7xx_gcr.c',
392
+ 'xlnx-can-test',
661
+ 'npcm7xx_mft.c',
393
'migration-test']
662
'npcm7xx_pwm.c',
394
663
'npcm7xx_rng.c',
395
qtests_s390x = \
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"
396
--
684
--
397
2.20.1
685
2.20.1
398
686
399
687
diff view generated by jsdifflib
1
In commit 077d7449100d824a4 we added code to handle the v8M
1
From: Hao Wu <wuhaotsh@google.com>
2
requirement that returns from NMI or HardFault forcibly deactivate
3
those exceptions regardless of what interrupt the guest is trying to
4
deactivate. Unfortunately this broke the handling of the "illegal
5
exception return because the returning exception number is not
6
active" check for those cases. In the pseudocode this test is done
7
on the exception the guest asks to return from, but because our
8
implementation was doing this in armv7m_nvic_complete_irq() after the
9
new "deactivate NMI/HardFault regardless" code we ended up doing the
10
test on the VecInfo for that exception instead, which usually meant
11
failing to raise the illegal exception return fault.
12
2
13
In the case for "configurable exception targeting the opposite
3
This patch adds the recently implemented MFT device to the NPCM7XX
14
security state" we detected the illegal-return case but went ahead
4
SoC file.
15
and deactivated the VecInfo anyway, which is wrong because that is
16
the VecInfo for the other security state.
17
5
18
Rearrange the code so that we first identify the illegal return
6
Reviewed-by: Doug Evans <dje@google.com>
19
cases, then see if we really need to deactivate NMI or HardFault
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
20
instead, and finally do the deactivation.
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>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
docs/system/arm/nuvoton.rst | 2 +-
14
include/hw/arm/npcm7xx.h | 2 ++
15
hw/arm/npcm7xx.c | 45 ++++++++++++++++++++++++++++++-------
16
3 files changed, 40 insertions(+), 9 deletions(-)
21
17
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 20201119215617.29887-25-peter.maydell@linaro.org
25
---
26
hw/intc/armv7m_nvic.c | 59 +++++++++++++++++++++++--------------------
27
1 file changed, 32 insertions(+), 27 deletions(-)
28
29
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
30
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/intc/armv7m_nvic.c
20
--- a/docs/system/arm/nuvoton.rst
32
+++ b/hw/intc/armv7m_nvic.c
21
+++ b/docs/system/arm/nuvoton.rst
33
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
22
@@ -XXX,XX +XXX,XX @@ Supported devices
34
{
23
* Pulse Width Modulation (PWM)
35
NVICState *s = (NVICState *)opaque;
24
* SMBus controller (SMBF)
36
VecInfo *vec = NULL;
25
* Ethernet controller (EMC)
37
- int ret;
26
+ * Tachometer
38
+ int ret = 0;
27
39
28
Missing devices
40
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
29
---------------
41
30
@@ -XXX,XX +XXX,XX @@ Missing devices
42
+ trace_nvic_complete_irq(irq, secure);
31
* Peripheral SPI controller (PSPI)
32
* SD/MMC host
33
* PECI interface
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
42
@@ -XXX,XX +XXX,XX @@
43
#include "hw/mem/npcm7xx_mc.h"
44
#include "hw/misc/npcm7xx_clk.h"
45
#include "hw/misc/npcm7xx_gcr.h"
46
+#include "hw/misc/npcm7xx_mft.h"
47
#include "hw/misc/npcm7xx_pwm.h"
48
#include "hw/misc/npcm7xx_rng.h"
49
#include "hw/net/npcm7xx_emc.h"
50
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
51
NPCM7xxTimerCtrlState tim[3];
52
NPCM7xxADCState adc;
53
NPCM7xxPWMState pwm[2];
54
+ NPCM7xxMFTState mft[8];
55
NPCM7xxOTPState key_storage;
56
NPCM7xxOTPState fuse_array;
57
NPCM7xxMCState mc;
58
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/hw/arm/npcm7xx.c
61
+++ b/hw/arm/npcm7xx.c
62
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
63
NPCM7XX_SMBUS15_IRQ,
64
NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
65
NPCM7XX_PWM1_IRQ, /* PWM module 1 */
66
+ NPCM7XX_MFT0_IRQ = 96, /* MFT module 0 */
67
+ NPCM7XX_MFT1_IRQ, /* MFT module 1 */
68
+ NPCM7XX_MFT2_IRQ, /* MFT module 2 */
69
+ NPCM7XX_MFT3_IRQ, /* MFT module 3 */
70
+ NPCM7XX_MFT4_IRQ, /* MFT module 4 */
71
+ NPCM7XX_MFT5_IRQ, /* MFT module 5 */
72
+ NPCM7XX_MFT6_IRQ, /* MFT module 6 */
73
+ NPCM7XX_MFT7_IRQ, /* MFT module 7 */
74
NPCM7XX_EMC2RX_IRQ = 114,
75
NPCM7XX_EMC2TX_IRQ,
76
NPCM7XX_GPIO0_IRQ = 116,
77
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_pwm_addr[] = {
78
0xf0104000,
79
};
80
81
+/* Register base address for each MFT Module */
82
+static const hwaddr npcm7xx_mft_addr[] = {
83
+ 0xf0180000,
84
+ 0xf0181000,
85
+ 0xf0182000,
86
+ 0xf0183000,
87
+ 0xf0184000,
88
+ 0xf0185000,
89
+ 0xf0186000,
90
+ 0xf0187000,
91
+};
43
+
92
+
44
+ if (secure && exc_is_banked(irq)) {
93
/* Direct memory-mapped access to each SMBus Module. */
45
+ vec = &s->sec_vectors[irq];
94
static const hwaddr npcm7xx_smbus_addr[] = {
46
+ } else {
95
0xf0080000,
47
+ vec = &s->vectors[irq];
96
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
97
object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
98
}
99
100
+ for (i = 0; i < ARRAY_SIZE(s->mft); i++) {
101
+ object_initialize_child(obj, "mft[*]", &s->mft[i], TYPE_NPCM7XX_MFT);
48
+ }
102
+ }
49
+
103
+
50
+ /*
104
for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
51
+ * Identify illegal exception return cases. We can't immediately
105
object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC);
52
+ * return at this point because we still need to deactivate
106
}
53
+ * (either this exception or NMI/HardFault) first.
107
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
54
+ */
108
sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
55
+ if (!exc_is_banked(irq) && exc_targets_secure(s, irq) != secure) {
109
}
56
+ /*
110
57
+ * Return from a configurable exception targeting the opposite
111
+ /* MFT Modules. Cannot fail. */
58
+ * security state from the one we're trying to complete it for.
112
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_mft_addr) != ARRAY_SIZE(s->mft));
59
+ * Clear vec because it's not really the VecInfo for this
113
+ for (i = 0; i < ARRAY_SIZE(s->mft); i++) {
60
+ * (irq, secstate) so we mustn't deactivate it.
114
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->mft[i]);
61
+ */
115
+
62
+ ret = -1;
116
+ qdev_connect_clock_in(DEVICE(&s->mft[i]), "clock-in",
63
+ vec = NULL;
117
+ qdev_get_clock_out(DEVICE(&s->clk),
64
+ } else if (!vec->active) {
118
+ "apb4-clock"));
65
+ /* Return from an inactive interrupt */
119
+ sysbus_realize(sbd, &error_abort);
66
+ ret = -1;
120
+ sysbus_mmio_map(sbd, 0, npcm7xx_mft_addr[i]);
67
+ } else {
121
+ sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, NPCM7XX_MFT0_IRQ + i));
68
+ /* Legal return, we will return the RETTOBASE bit value to the caller */
69
+ ret = nvic_rettobase(s);
70
+ }
122
+ }
71
+
123
+
72
/*
124
/*
73
* For negative priorities, v8M will forcibly deactivate the appropriate
125
* EMC Modules. Cannot fail.
74
* NMI or HardFault regardless of what interrupt we're being asked to
126
* The mapping of the device to its netdev backend works as follows:
75
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
127
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
76
}
128
create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
77
129
create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
78
if (!vec) {
130
create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
79
- if (secure && exc_is_banked(irq)) {
131
- create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB);
80
- vec = &s->sec_vectors[irq];
132
- create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB);
81
- } else {
133
- create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB);
82
- vec = &s->vectors[irq];
134
- create_unimplemented_device("npcm7xx.mft[3]", 0xf0183000, 4 * KiB);
83
- }
135
- create_unimplemented_device("npcm7xx.mft[4]", 0xf0184000, 4 * KiB);
84
- }
136
- create_unimplemented_device("npcm7xx.mft[5]", 0xf0185000, 4 * KiB);
85
-
137
- create_unimplemented_device("npcm7xx.mft[6]", 0xf0186000, 4 * KiB);
86
- trace_nvic_complete_irq(irq, secure);
138
- create_unimplemented_device("npcm7xx.mft[7]", 0xf0187000, 4 * KiB);
87
-
139
create_unimplemented_device("npcm7xx.pspi1", 0xf0200000, 4 * KiB);
88
- if (!vec->active) {
140
create_unimplemented_device("npcm7xx.pspi2", 0xf0201000, 4 * KiB);
89
- /* Tell the caller this was an illegal exception return */
141
create_unimplemented_device("npcm7xx.ahbpci", 0xf0400000, 1 * MiB);
90
- return -1;
91
- }
92
-
93
- /*
94
- * If this is a configurable exception and it is currently
95
- * targeting the opposite security state from the one we're trying
96
- * to complete it for, this counts as an illegal exception return.
97
- * We still need to deactivate whatever vector the logic above has
98
- * selected, though, as it might not be the same as the one for the
99
- * requested exception number.
100
- */
101
- if (!exc_is_banked(irq) && exc_targets_secure(s, irq) != secure) {
102
- ret = -1;
103
- } else {
104
- ret = nvic_rettobase(s);
105
+ return ret;
106
}
107
108
vec->active = 0;
109
--
142
--
110
2.20.1
143
2.20.1
111
144
112
145
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Dump the collected random data after a randomness test failure.
3
This patch adds fan_splitters (split IRQs) in NPCM7XX boards. Each fan
4
4
splitter corresponds to 1 PWM output and can connect to multiple fan
5
Note that this relies on the test having called
5
inputs (MFT devices).
6
g_test_set_nonfatal_assertions() so we don't abort immediately on the
6
In NPCM7XX boards(NPCM750 EVB and Quanta GSJ boards), we initializes
7
assertion failure.
7
these splitters and connect them to their corresponding modules
8
8
according their specific device trees.
9
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
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>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
[PMM: minor commit message tweak]
14
Message-id: 20210311180855.149764-5-wuhaotsh@google.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
16
---
14
tests/qtest/npcm7xx_rng-test.c | 12 ++++++++++++
17
include/hw/arm/npcm7xx.h | 11 ++++-
15
1 file changed, 12 insertions(+)
18
hw/arm/npcm7xx_boards.c | 99 ++++++++++++++++++++++++++++++++++++++++
16
19
2 files changed, 109 insertions(+), 1 deletion(-)
17
diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c
20
21
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
18
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qtest/npcm7xx_rng-test.c
23
--- a/include/hw/arm/npcm7xx.h
20
+++ b/tests/qtest/npcm7xx_rng-test.c
24
+++ b/include/hw/arm/npcm7xx.h
21
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@
22
26
23
#include "libqtest-single.h"
27
#include "hw/boards.h"
24
#include "qemu/bitops.h"
28
#include "hw/adc/npcm7xx_adc.h"
25
+#include "qemu-common.h"
29
+#include "hw/core/split-irq.h"
26
30
#include "hw/cpu/a9mpcore.h"
27
#define RNG_BASE_ADDR 0xf000b000
31
#include "hw/gpio/npcm7xx_gpio.h"
28
32
#include "hw/i2c/npcm7xx_smbus.h"
29
@@ -XXX,XX +XXX,XX @@
33
@@ -XXX,XX +XXX,XX @@
30
/* Number of bits to collect for randomness tests. */
34
#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
31
#define TEST_INPUT_BITS (128)
35
#define NPCM7XX_BOARD_SETUP_ADDR (0xffff1000) /* Boot ROM */
32
36
33
+static void dump_buf_if_failed(const uint8_t *buf, size_t size)
37
+#define NPCM7XX_NR_PWM_MODULES 2
34
+{
38
+
35
+ if (g_test_failed()) {
39
typedef struct NPCM7xxMachine {
36
+ qemu_hexdump(stderr, "", buf, size);
40
MachineState parent;
41
+ /*
42
+ * PWM fan splitter. each splitter connects to one PWM output and
43
+ * multiple MFT inputs.
44
+ */
45
+ SplitIRQ fan_splitter[NPCM7XX_NR_PWM_MODULES *
46
+ NPCM7XX_PWM_PER_MODULE];
47
} NPCM7xxMachine;
48
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
60
index XXXXXXX..XXXXXXX 100644
61
--- a/hw/arm/npcm7xx_boards.c
62
+++ b/hw/arm/npcm7xx_boards.c
63
@@ -XXX,XX +XXX,XX @@
64
#include "hw/core/cpu.h"
65
#include "hw/i2c/smbus_eeprom.h"
66
#include "hw/loader.h"
67
+#include "hw/qdev-core.h"
68
#include "hw/qdev-properties.h"
69
#include "qapi/error.h"
70
#include "qemu-common.h"
71
@@ -XXX,XX +XXX,XX @@ static void at24c_eeprom_init(NPCM7xxState *soc, int bus, uint8_t addr,
72
i2c_slave_realize_and_unref(i2c_dev, i2c_bus, &error_abort);
73
}
74
75
+static void npcm7xx_init_pwm_splitter(NPCM7xxMachine *machine,
76
+ NPCM7xxState *soc, const int *fan_counts)
77
+{
78
+ SplitIRQ *splitters = machine->fan_splitter;
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));
100
+ }
37
+ }
101
+ }
38
+}
102
+}
39
+
103
+
40
static void rng_writeb(unsigned int offset, uint8_t value)
104
+static void npcm7xx_connect_pwm_fan(NPCM7xxState *soc, SplitIRQ *splitter,
105
+ int fan_no, int output_no)
106
+{
107
+ DeviceState *fan;
108
+ int fan_input;
109
+ qemu_irq fan_duty_gpio;
110
+
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)
41
{
134
{
42
writeb(RNG_BASE_ADDR + offset, value);
135
/* lm75 temperature sensor on SVB, tmp105 is compatible */
43
@@ -XXX,XX +XXX,XX @@ static void test_continuous_monobit(void)
136
@@ -XXX,XX +XXX,XX @@ static void npcm750_evb_i2c_init(NPCM7xxState *soc)
44
}
137
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 6), "tmp105", 0x48);
45
138
}
46
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
139
47
+ dump_buf_if_failed(buf, sizeof(buf));
140
+static void npcm750_evb_fan_init(NPCM7xxMachine *machine, NPCM7xxState *soc)
48
}
141
+{
49
142
+ SplitIRQ *splitter = machine->fan_splitter;
50
/*
143
+ static const int fan_counts[] = {2, 2, 2, 2, 2, 2, 2, 2};
51
@@ -XXX,XX +XXX,XX @@ static void test_continuous_runs(void)
144
+
52
}
145
+ npcm7xx_init_pwm_splitter(machine, soc, fan_counts);
53
146
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x00, 0);
54
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
147
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x01, 1);
55
+ dump_buf_if_failed(buf.c, sizeof(buf));
148
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x02, 0);
56
}
149
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x03, 1);
57
150
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x04, 0);
58
/*
151
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x05, 1);
59
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_monobit(void)
152
+ npcm7xx_connect_pwm_fan(soc, &splitter[3], 0x06, 0);
60
}
153
+ npcm7xx_connect_pwm_fan(soc, &splitter[3], 0x07, 1);
61
154
+ npcm7xx_connect_pwm_fan(soc, &splitter[4], 0x08, 0);
62
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
155
+ npcm7xx_connect_pwm_fan(soc, &splitter[4], 0x09, 1);
63
+ dump_buf_if_failed(buf, sizeof(buf));
156
+ npcm7xx_connect_pwm_fan(soc, &splitter[5], 0x0a, 0);
64
}
157
+ npcm7xx_connect_pwm_fan(soc, &splitter[5], 0x0b, 1);
65
158
+ npcm7xx_connect_pwm_fan(soc, &splitter[6], 0x0c, 0);
66
/*
159
+ npcm7xx_connect_pwm_fan(soc, &splitter[6], 0x0d, 1);
67
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_runs(void)
160
+ npcm7xx_connect_pwm_fan(soc, &splitter[7], 0x0e, 0);
68
}
161
+ npcm7xx_connect_pwm_fan(soc, &splitter[7], 0x0f, 1);
69
162
+}
70
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
163
+
71
+ dump_buf_if_failed(buf.c, sizeof(buf));
164
static void quanta_gsj_i2c_init(NPCM7xxState *soc)
72
}
165
{
73
166
/* GSJ machine have 4 max31725 temperature sensors, tmp105 is compatible. */
74
int main(int argc, char **argv)
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
}
203
75
--
204
--
76
2.20.1
205
2.20.1
77
206
78
207
diff view generated by jsdifflib
1
In v8.1M the new CLRM instruction allows zeroing an arbitrary set of
1
From: Hao Wu <wuhaotsh@google.com>
2
the general-purpose registers and APSR. Implement this.
2
3
3
This patch adds testing of PWM fan RPMs in the existing npcm7xx pwm
4
The encoding is a subset of the LDMIA T2 encoding, using what would
4
test. It tests whether the MFT module can measure correct fan values
5
be Rn=0b1111 (which UNDEFs for LDMIA).
5
for a PWM fan in NPCM7XX boards.
6
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>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20210311180855.149764-6-wuhaotsh@google.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20201119215617.29887-6-peter.maydell@linaro.org
10
---
13
---
11
target/arm/t32.decode | 6 +++++-
14
tests/qtest/npcm7xx_pwm-test.c | 205 ++++++++++++++++++++++++++++++++-
12
target/arm/translate.c | 38 ++++++++++++++++++++++++++++++++++++++
15
1 file changed, 199 insertions(+), 6 deletions(-)
13
2 files changed, 43 insertions(+), 1 deletion(-)
16
14
17
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
15
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/t32.decode
19
--- a/tests/qtest/npcm7xx_pwm-test.c
18
+++ b/target/arm/t32.decode
20
+++ b/tests/qtest/npcm7xx_pwm-test.c
19
@@ -XXX,XX +XXX,XX @@ UXTAB 1111 1010 0101 .... 1111 .... 10.. .... @rrr_rot
21
@@ -XXX,XX +XXX,XX @@
20
22
#define PLL_FBDV(rv) extract32((rv), 16, 12)
21
STM_t32 1110 1000 10.0 .... ................ @ldstm i=1 b=0
23
#define PLL_OTDV1(rv) extract32((rv), 8, 3)
22
STM_t32 1110 1001 00.0 .... ................ @ldstm i=0 b=1
24
#define PLL_OTDV2(rv) extract32((rv), 13, 3)
23
-LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
25
+#define APB4CKDIV(rv) extract32((rv), 30, 2)
24
+{
26
#define APB3CKDIV(rv) extract32((rv), 28, 2)
25
+ # Rn=15 UNDEFs for LDM; M-profile CLRM uses that encoding
27
#define CLK2CKDIV(rv) extract32((rv), 0, 1)
26
+ CLRM 1110 1000 1001 1111 list:16
28
#define CLK4CKDIV(rv) extract32((rv), 26, 2)
27
+ LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
29
@@ -XXX,XX +XXX,XX @@
28
+}
30
29
LDM_t32 1110 1001 00.1 .... ................ @ldstm i=0 b=1
31
#define MAX_DUTY 1000000
30
32
31
&rfe !extern rn w pu
33
+/* MFT (PWM fan) related */
32
diff --git a/target/arm/translate.c b/target/arm/translate.c
34
+#define MFT_BA(n) (0xf0180000 + ((n) * 0x1000))
33
index XXXXXXX..XXXXXXX 100644
35
+#define MFT_IRQ(n) (96 + (n))
34
--- a/target/arm/translate.c
36
+#define MFT_CNT1 0x00
35
+++ b/target/arm/translate.c
37
+#define MFT_CRA 0x02
36
@@ -XXX,XX +XXX,XX @@ static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
38
+#define MFT_CRB 0x04
37
return do_ldm(s, a, 1);
39
+#define MFT_CNT2 0x06
38
}
40
+#define MFT_PRSC 0x08
39
41
+#define MFT_CKC 0x0a
40
+static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
42
+#define MFT_MCTRL 0x0c
41
+{
43
+#define MFT_ICTRL 0x0e
42
+ int i;
44
+#define MFT_ICLR 0x10
43
+ TCGv_i32 zero;
45
+#define MFT_IEN 0x12
44
+
46
+#define MFT_CPA 0x14
45
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
47
+#define MFT_CPB 0x16
46
+ return false;
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;
47
+ }
219
+ }
48
+
220
+
49
+ if (extract32(a->list, 13, 1)) {
221
+ cnt = clk * 60 / ((DEFAULT_PRSC + 1) * rpm * MFT_PULSE_PER_REVOLUTION);
50
+ return false;
222
+ if (cnt >= MFT_TIMEOUT) {
223
+ return -1;
51
+ }
224
+ }
52
+
225
+ return MFT_MAX_CNT - cnt;
53
+ if (!a->list) {
226
+}
54
+ /* UNPREDICTABLE; we choose to UNDEF */
227
+
55
+ return false;
228
+static void mft_verify_rpm(QTestState *qts, const TestData *td, uint64_t duty)
229
+{
230
+ int index = mft_compute_index(td);
231
+ uint16_t cnt, cr;
232
+ uint32_t rpm = DEFAULT_RPM * duty / MAX_DUTY;
233
+ uint64_t clk = read_pclk(qts, true);
234
+ int32_t expected_cnt = mft_compute_cnt(rpm, clk);
235
+
236
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
237
+ g_test_message(
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);
255
+ } else {
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);
56
+ }
266
+ }
57
+
267
+
58
+ zero = tcg_const_i32(0);
268
+ /* Verify rpm for fan B */
59
+ for (i = 0; i < 15; i++) {
269
+
60
+ if (extract32(a->list, i, 1)) {
270
+ qtest_irq_intercept_out(qts, "/machine/soc/a9mpcore/gic");
61
+ /* Clear R[i] */
271
+}
62
+ tcg_gen_mov_i32(cpu_R[i], zero);
272
+
63
+ }
273
/* Check pwm registers can be reset to default value */
64
+ }
274
static void test_init(gconstpointer test_data)
65
+ if (extract32(a->list, 15, 1)) {
275
{
66
+ /*
276
const TestData *td = test_data;
67
+ * Clear APSR (by calling the MSR helper with the same argument
277
- QTestState *qts = qtest_init("-machine quanta-gsj");
68
+ * as for "MSR APSR_nzcvqg, Rn": mask = 0b1100, SYSM=0)
278
+ QTestState *qts = qtest_init("-machine npcm750-evb");
69
+ */
279
int module = pwm_module_index(td->module);
70
+ TCGv_i32 maskreg = tcg_const_i32(0xc << 8);
280
int pwm = pwm_index(td->pwm);
71
+ gen_helper_v7m_msr(cpu_env, maskreg, zero);
281
72
+ tcg_temp_free_i32(maskreg);
282
@@ -XXX,XX +XXX,XX @@ static void test_init(gconstpointer test_data)
73
+ }
283
static void test_oneshot(gconstpointer test_data)
74
+ tcg_temp_free_i32(zero);
284
{
75
+ return true;
285
const TestData *td = test_data;
76
+}
286
- QTestState *qts = qtest_init("-machine quanta-gsj");
77
+
287
+ QTestState *qts = qtest_init("-machine npcm750-evb");
78
/*
288
int module = pwm_module_index(td->module);
79
* Branch, branch with link
289
int pwm = pwm_index(td->pwm);
80
*/
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);
310
}
311
312
+ /* Test MFT's RPM is correct. */
313
+ mft_verify_rpm(qts, td, expected_duty);
314
+
315
/* Test inverted mode */
316
expected_duty = pwm_compute_duty(cnr, cmr, true);
317
pwm_write_pcr(qts, td, pcr | CH_INV);
81
--
318
--
82
2.20.1
319
2.20.1
83
320
84
321
diff view generated by jsdifflib
1
In arm_cpu_realizefn() we check whether the board code disabled EL3
1
For a long time now the UI layer has guaranteed that the console
2
via the has_el3 CPU object property, which we create if the CPU
2
surface is always 32 bits per pixel. Remove the legacy dead
3
starts with the ARM_FEATURE_EL3 feature bit. If it is disabled, then
3
code from the pl110 display device which was handling the
4
we turn off ARM_FEATURE_EL3 and also zero out the relevant fields in
4
possibility that the console surface was some other format.
5
the ID_PFR1 and ID_AA64PFR0 registers.
6
7
This codepath was incorrectly being taken for M-profile CPUs, which
8
do not have an EL3 and don't set ARM_FEATURE_EL3, but which may have
9
the M-profile Security extension and so should have non-zero values
10
in the ID_PFR1.Security field.
11
12
Restrict the handling of the feature flag to A/R-profile cores.
13
5
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
16
Message-id: 20201119215617.29887-4-peter.maydell@linaro.org
8
Message-id: 20210211141515.8755-2-peter.maydell@linaro.org
17
---
9
---
18
target/arm/cpu.c | 2 +-
10
hw/display/pl110.c | 53 +++++++---------------------------------------
19
1 file changed, 1 insertion(+), 1 deletion(-)
11
1 file changed, 8 insertions(+), 45 deletions(-)
20
12
21
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
22
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.c
15
--- a/hw/display/pl110.c
24
+++ b/target/arm/cpu.c
16
+++ b/hw/display/pl110.c
25
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
17
@@ -XXX,XX +XXX,XX @@ static const unsigned char *idregs[] = {
18
pl111_id
19
};
20
21
-#define BITS 8
22
-#include "pl110_template.h"
23
-#define BITS 15
24
-#include "pl110_template.h"
25
-#define BITS 16
26
-#include "pl110_template.h"
27
-#define BITS 24
28
-#include "pl110_template.h"
29
#define BITS 32
30
#include "pl110_template.h"
31
32
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
33
PL110State *s = (PL110State *)opaque;
34
SysBusDevice *sbd;
35
DisplaySurface *surface = qemu_console_surface(s->con);
36
- drawfn* fntable;
37
drawfn fn;
38
- int dest_width;
39
int src_width;
40
int bpp_offset;
41
int first;
42
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
43
44
sbd = SYS_BUS_DEVICE(s);
45
46
- switch (surface_bits_per_pixel(surface)) {
47
- case 0:
48
- return;
49
- case 8:
50
- fntable = pl110_draw_fn_8;
51
- dest_width = 1;
52
- break;
53
- case 15:
54
- fntable = pl110_draw_fn_15;
55
- dest_width = 2;
56
- break;
57
- case 16:
58
- fntable = pl110_draw_fn_16;
59
- dest_width = 2;
60
- break;
61
- case 24:
62
- fntable = pl110_draw_fn_24;
63
- dest_width = 3;
64
- break;
65
- case 32:
66
- fntable = pl110_draw_fn_32;
67
- dest_width = 4;
68
- break;
69
- default:
70
- fprintf(stderr, "pl110: Bad color depth\n");
71
- exit(1);
72
- }
73
if (s->cr & PL110_CR_BGR)
74
bpp_offset = 0;
75
else
76
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
26
}
77
}
27
}
78
}
28
79
29
- if (!cpu->has_el3) {
80
- if (s->cr & PL110_CR_BEBO)
30
+ if (!arm_feature(env, ARM_FEATURE_M) && !cpu->has_el3) {
81
- fn = fntable[s->bpp + 8 + bpp_offset];
31
/* If the has_el3 CPU property is disabled then we need to disable the
82
- else if (s->cr & PL110_CR_BEPO)
32
* feature.
83
- fn = fntable[s->bpp + 16 + bpp_offset];
33
*/
84
- else
85
- fn = fntable[s->bpp + bpp_offset];
86
+ if (s->cr & PL110_CR_BEBO) {
87
+ fn = pl110_draw_fn_32[s->bpp + 8 + bpp_offset];
88
+ } else if (s->cr & PL110_CR_BEPO) {
89
+ fn = pl110_draw_fn_32[s->bpp + 16 + bpp_offset];
90
+ } else {
91
+ fn = pl110_draw_fn_32[s->bpp + bpp_offset];
92
+ }
93
94
src_width = s->cols;
95
switch (s->bpp) {
96
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
97
src_width <<= 2;
98
break;
99
}
100
- dest_width *= s->cols;
101
first = 0;
102
if (s->invalidate) {
103
framebuffer_update_memory_section(&s->fbsection,
104
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
105
106
framebuffer_update_display(surface, &s->fbsection,
107
s->cols, s->rows,
108
- src_width, dest_width, 0,
109
+ src_width, s->cols * 4, 0,
110
s->invalidate,
111
fn, s->palette,
112
&first, &last);
34
--
113
--
35
2.20.1
114
2.20.1
36
115
37
116
diff view generated by jsdifflib
1
In v8.0M, on exception entry the registers R0-R3, R12, APSR and EPSR
1
The pl110_template.h header has a doubly-nested multiple-include pattern:
2
are zeroed for an exception taken to Non-secure state; for an
2
* pl110.c includes it once for each host bit depth (now always 32)
3
exception taken to Secure state they become UNKNOWN, and we chose to
3
* every time it is included, it includes itself 6 times, to account
4
leave them at their previous values.
4
for multiple guest device pixel and byte orders
5
5
6
In v8.1M the behaviour is specified more tightly and these registers
6
Now we only have to deal with 32-bit host bit depths, we can move the
7
are always zeroed regardless of the security state that the exception
7
code corresponding to the outer layer of this double-nesting to be
8
targets (see rule R_KPZV). Implement this.
8
directly in pl110.c and reduce the template header to a single layer
9
of nesting.
9
10
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
12
Message-id: 20201119215617.29887-17-peter.maydell@linaro.org
13
Message-id: 20210211141515.8755-3-peter.maydell@linaro.org
13
---
14
---
14
target/arm/m_helper.c | 16 ++++++++++++----
15
hw/display/pl110_template.h | 100 +-----------------------------------
15
1 file changed, 12 insertions(+), 4 deletions(-)
16
hw/display/pl110.c | 79 ++++++++++++++++++++++++++++
16
17
2 files changed, 80 insertions(+), 99 deletions(-)
17
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
18
19
diff --git a/hw/display/pl110_template.h b/hw/display/pl110_template.h
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/m_helper.c
21
--- a/hw/display/pl110_template.h
20
+++ b/target/arm/m_helper.c
22
+++ b/hw/display/pl110_template.h
21
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
23
@@ -XXX,XX +XXX,XX @@
22
* Clear registers if necessary to prevent non-secure exception
24
*/
23
* code being able to see register values from secure code.
25
24
* Where register values become architecturally UNKNOWN we leave
26
#ifndef ORDER
25
- * them with their previous values.
27
-
26
+ * them with their previous values. v8.1M is tighter than v8.0M
28
-#if BITS == 8
27
+ * here and always zeroes the caller-saved registers regardless
29
-#define COPY_PIXEL(to, from) *(to++) = from
28
+ * of the security state the exception is targeting.
30
-#elif BITS == 15 || BITS == 16
29
*/
31
-#define COPY_PIXEL(to, from) do { *(uint16_t *)to = from; to += 2; } while (0)
30
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
32
-#elif BITS == 24
31
- if (!targets_secure) {
33
-#define COPY_PIXEL(to, from) \
32
+ if (!targets_secure || arm_feature(env, ARM_FEATURE_V8_1M)) {
34
- do { \
33
/*
35
- *(to++) = from; \
34
* Always clear the caller-saved registers (they have been
36
- *(to++) = (from) >> 8; \
35
* pushed to the stack earlier in v7m_push_stack()).
37
- *(to++) = (from) >> 16; \
36
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
38
- } while (0)
37
* v7m_push_callee_stack()).
39
-#elif BITS == 32
38
*/
40
-#define COPY_PIXEL(to, from) do { *(uint32_t *)to = from; to += 4; } while (0)
39
int i;
41
-#else
40
+ /*
42
-#error unknown bit depth
41
+ * r4..r11 are callee-saves, zero only if background
43
+#error "pl110_template.h is only for inclusion by pl110.c"
42
+ * state was Secure (EXCRET.S == 1) and exception
44
#endif
43
+ * targets Non-secure state
45
44
+ */
46
-#undef RGB
45
+ bool zero_callee_saves = !targets_secure &&
47
-#define BORDER bgr
46
+ (lr & R_V7M_EXCRET_S_MASK);
48
-#define ORDER 0
47
49
-#include "pl110_template.h"
48
for (i = 0; i < 13; i++) {
50
-#define ORDER 1
49
- /* r4..r11 are callee-saves, zero only if EXCRET.S == 1 */
51
-#include "pl110_template.h"
50
- if (i < 4 || i > 11 || (lr & R_V7M_EXCRET_S_MASK)) {
52
-#define ORDER 2
51
+ if (i < 4 || i > 11 || zero_callee_saves) {
53
-#include "pl110_template.h"
52
env->regs[i] = 0;
54
-#undef BORDER
53
}
55
-#define RGB
54
}
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[] = {
141
};
142
143
#define BITS 32
144
+#define COPY_PIXEL(to, from) do { *(uint32_t *)to = from; to += 4; } while (0)
145
+
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,
219
+};
220
+
221
+#undef BITS
222
+#undef COPY_PIXEL
223
+
224
225
static int pl110_enabled(PL110State *s)
226
{
55
--
227
--
56
2.20.1
228
2.20.1
57
229
58
230
diff view generated by jsdifflib
1
The FPDSCR register has a similar layout to the FPSCR. In v8.1M it
1
BITS is always 32, so remove all uses of it from the template header,
2
gains new fields FZ16 (if half-precision floating point is supported)
2
by dropping the trailing '32' from the draw function names and
3
and LTPSIZE (always reads as 4). Update the reset value and the code
3
not constructing the name of rgb_to_pixel32() via the glue() macro.
4
that handles writes to this register accordingly.
5
4
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
8
Message-id: 20201119215617.29887-16-peter.maydell@linaro.org
7
Message-id: 20210211141515.8755-4-peter.maydell@linaro.org
9
---
8
---
10
target/arm/cpu.h | 5 +++++
9
hw/display/pl110_template.h | 20 +++----
11
hw/intc/armv7m_nvic.c | 9 ++++++++-
10
hw/display/pl110.c | 113 ++++++++++++++++++------------------
12
target/arm/cpu.c | 3 +++
11
2 files changed, 65 insertions(+), 68 deletions(-)
13
3 files changed, 16 insertions(+), 1 deletion(-)
12
14
13
diff --git a/hw/display/pl110_template.h b/hw/display/pl110_template.h
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
15
--- a/hw/display/pl110_template.h
18
+++ b/target/arm/cpu.h
16
+++ b/hw/display/pl110_template.h
19
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
17
@@ -XXX,XX +XXX,XX @@
20
#define FPCR_IXE (1 << 12) /* Inexact exception trap enable */
18
#endif
21
#define FPCR_IDE (1 << 15) /* Input Denormal exception trap enable */
19
22
#define FPCR_FZ16 (1 << 19) /* ARMv8.2+, FP16 flush-to-zero */
20
#if ORDER == 0
23
+#define FPCR_RMODE_MASK (3 << 22) /* Rounding mode */
21
-#define NAME glue(glue(lblp_, BORDER), BITS)
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
22
+#define NAME glue(lblp_, BORDER)
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
23
#ifdef HOST_WORDS_BIGENDIAN
26
+#define FPCR_AHP (1 << 26) /* Alternative half-precision */
24
#define SWAP_WORDS 1
27
#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
25
#endif
28
#define FPCR_V (1 << 28) /* FP overflow flag */
26
#elif ORDER == 1
29
#define FPCR_C (1 << 29) /* FP carry flag */
27
-#define NAME glue(glue(bbbp_, BORDER), BITS)
30
#define FPCR_Z (1 << 30) /* FP zero flag */
28
+#define NAME glue(bbbp_, BORDER)
31
#define FPCR_N (1 << 31) /* FP negative flag */
29
#ifndef HOST_WORDS_BIGENDIAN
32
30
#define SWAP_WORDS 1
33
+#define FPCR_LTPSIZE_SHIFT 16 /* LTPSIZE, M-profile only */
31
#endif
34
+#define FPCR_LTPSIZE_MASK (7 << FPCR_LTPSIZE_SHIFT)
32
#else
35
+
33
#define SWAP_PIXELS 1
36
#define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
34
-#define NAME glue(glue(lbbp_, BORDER), BITS)
37
#define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
35
+#define NAME glue(lbbp_, BORDER)
38
36
#ifdef HOST_WORDS_BIGENDIAN
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
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
40
index XXXXXXX..XXXXXXX 100644
100
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/intc/armv7m_nvic.c
101
--- a/hw/display/pl110.c
42
+++ b/hw/intc/armv7m_nvic.c
102
+++ b/hw/display/pl110.c
43
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
103
@@ -XXX,XX +XXX,XX @@ static const unsigned char *idregs[] = {
44
break;
104
pl111_id
45
case 0xf3c: /* FPDSCR */
105
};
46
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
106
47
- value &= 0x07c00000;
107
-#define BITS 32
48
+ uint32_t mask = FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK;
108
#define COPY_PIXEL(to, from) do { *(uint32_t *)to = from; to += 4; } while (0)
49
+ if (cpu_isar_feature(any_fp16, cpu)) {
109
50
+ mask |= FPCR_FZ16;
110
#undef RGB
51
+ }
111
@@ -XXX,XX +XXX,XX @@ static const unsigned char *idregs[] = {
52
+ value &= mask;
112
#include "pl110_template.h"
53
+ if (cpu_isar_feature(aa32_lob, cpu)) {
113
#undef BORDER
54
+ value |= 4 << FPCR_LTPSIZE_SHIFT;
114
55
+ }
115
-static drawfn pl110_draw_fn_32[48] = {
56
cpu->env.v7m.fpdscr[attrs.secure] = value;
116
- pl110_draw_line1_lblp_bgr32,
57
}
117
- pl110_draw_line2_lblp_bgr32,
58
break;
118
- pl110_draw_line4_lblp_bgr32,
59
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
119
- pl110_draw_line8_lblp_bgr32,
60
index XXXXXXX..XXXXXXX 100644
120
- pl110_draw_line16_555_lblp_bgr32,
61
--- a/target/arm/cpu.c
121
- pl110_draw_line32_lblp_bgr32,
62
+++ b/target/arm/cpu.c
122
- pl110_draw_line16_lblp_bgr32,
63
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
123
- pl110_draw_line12_lblp_bgr32,
64
* always reset to 4.
124
-
65
*/
125
- pl110_draw_line1_bbbp_bgr32,
66
env->v7m.ltpsize = 4;
126
- pl110_draw_line2_bbbp_bgr32,
67
+ /* The LTPSIZE field in FPDSCR is constant and reads as 4. */
127
- pl110_draw_line4_bbbp_bgr32,
68
+ env->v7m.fpdscr[M_REG_NS] = 4 << FPCR_LTPSIZE_SHIFT;
128
- pl110_draw_line8_bbbp_bgr32,
69
+ env->v7m.fpdscr[M_REG_S] = 4 << FPCR_LTPSIZE_SHIFT;
129
- pl110_draw_line16_555_bbbp_bgr32,
70
}
130
- pl110_draw_line32_bbbp_bgr32,
71
131
- pl110_draw_line16_bbbp_bgr32,
72
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
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)
231
{
73
--
232
--
74
2.20.1
233
2.20.1
75
234
76
235
diff view generated by jsdifflib
1
Implement the new-in-v8.1M VLDR/VSTR variants which directly
1
For a long time now the UI layer has guaranteed that the console
2
read or write FP system registers to memory.
2
surface is always 32 bits per pixel. Remove the legacy dead code
3
from the pxa2xx_lcd display device which was handling the possibility
4
that the console surface was some other format.
3
5
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
6
Message-id: 20201119215617.29887-10-peter.maydell@linaro.org
8
Message-id: 20210211141515.8755-5-peter.maydell@linaro.org
7
---
9
---
8
target/arm/vfp.decode | 14 ++++++
10
hw/display/pxa2xx_lcd.c | 79 +++++++++--------------------------------
9
target/arm/translate-vfp.c.inc | 91 ++++++++++++++++++++++++++++++++++
11
1 file changed, 17 insertions(+), 62 deletions(-)
10
2 files changed, 105 insertions(+)
11
12
12
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
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/vfp.decode
15
--- a/hw/display/pxa2xx_lcd.c
15
+++ b/target/arm/vfp.decode
16
+++ b/hw/display/pxa2xx_lcd.c
16
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR_hp ---- 1101 u:1 .0 l:1 rn:4 .... 1001 imm:8 vd=%vd_sp
17
@@ -XXX,XX +XXX,XX @@ struct PXA2xxLCDState {
17
VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp
18
18
VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp
19
int invalidated;
19
20
QemuConsole *con;
20
+# M-profile VLDR/VSTR to sysreg
21
- drawfn *line_fn[2];
21
+%vldr_sysreg 22:1 13:3
22
int dest_width;
22
+%imm7_0x4 0:7 !function=times_4
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"
23
+
31
+
24
+&vldr_sysreg rn reg imm a w p
32
/* Route internal interrupt lines to the global IC */
25
+@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
33
static void pxa2xx_lcdc_int_update(PXA2xxLCDState *s)
26
+ reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
34
{
27
+
35
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
28
+# P=0 W=0 is SEE "Related encodings", so split into two patterns
36
}
29
+VLDR_sysreg ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
30
+VLDR_sysreg ---- 110 0 . . 1 1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
31
+VSTR_sysreg ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
32
+VSTR_sysreg ---- 110 0 . . 1 0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
33
+
34
# We split the load/store multiple up into two patterns to avoid
35
# overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
36
# grouping:
37
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate-vfp.c.inc
40
+++ b/target/arm/translate-vfp.c.inc
41
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
42
return true;
43
}
37
}
44
38
45
+static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
39
+static inline drawfn pxa2xx_drawfn(PXA2xxLCDState *s)
46
+{
40
+{
47
+ arg_vldr_sysreg *a = opaque;
41
+ if (s->transp) {
48
+ uint32_t offset = a->imm;
42
+ return pxa2xx_draw_fn_32t[s->bpp];
49
+ TCGv_i32 addr;
50
+
51
+ if (!a->a) {
52
+ offset = - offset;
53
+ }
54
+
55
+ addr = load_reg(s, a->rn);
56
+ if (a->p) {
57
+ tcg_gen_addi_i32(addr, addr, offset);
58
+ }
59
+
60
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
61
+ gen_helper_v8m_stackcheck(cpu_env, addr);
62
+ }
63
+
64
+ gen_aa32_st_i32(s, value, addr, get_mem_index(s),
65
+ MO_UL | MO_ALIGN | s->be_data);
66
+ tcg_temp_free_i32(value);
67
+
68
+ if (a->w) {
69
+ /* writeback */
70
+ if (!a->p) {
71
+ tcg_gen_addi_i32(addr, addr, offset);
72
+ }
73
+ store_reg(s, a->rn, addr);
74
+ } else {
43
+ } else {
75
+ tcg_temp_free_i32(addr);
44
+ return pxa2xx_draw_fn_32[s->bpp];
76
+ }
45
+ }
77
+}
46
+}
78
+
47
+
79
+static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
48
static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
80
+{
49
hwaddr addr, int *miny, int *maxy)
81
+ arg_vldr_sysreg *a = opaque;
82
+ uint32_t offset = a->imm;
83
+ TCGv_i32 addr;
84
+ TCGv_i32 value = tcg_temp_new_i32();
85
+
86
+ if (!a->a) {
87
+ offset = - offset;
88
+ }
89
+
90
+ addr = load_reg(s, a->rn);
91
+ if (a->p) {
92
+ tcg_gen_addi_i32(addr, addr, offset);
93
+ }
94
+
95
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
96
+ gen_helper_v8m_stackcheck(cpu_env, addr);
97
+ }
98
+
99
+ gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
100
+ MO_UL | MO_ALIGN | s->be_data);
101
+
102
+ if (a->w) {
103
+ /* writeback */
104
+ if (!a->p) {
105
+ tcg_gen_addi_i32(addr, addr, offset);
106
+ }
107
+ store_reg(s, a->rn, addr);
108
+ } else {
109
+ tcg_temp_free_i32(addr);
110
+ }
111
+ return value;
112
+}
113
+
114
+static bool trans_VLDR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
115
+{
116
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
117
+ return false;
118
+ }
119
+ if (a->rn == 15) {
120
+ return false;
121
+ }
122
+ return gen_M_fp_sysreg_write(s, a->reg, memory_to_fp_sysreg, a);
123
+}
124
+
125
+static bool trans_VSTR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
126
+{
127
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
128
+ return false;
129
+ }
130
+ if (a->rn == 15) {
131
+ return false;
132
+ }
133
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_memory, a);
134
+}
135
+
136
static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
137
{
50
{
138
TCGv_i32 tmp;
51
DisplaySurface *surface = qemu_console_surface(s->con);
52
int src_width, dest_width;
53
- drawfn fn = NULL;
54
- if (s->dest_width)
55
- fn = s->line_fn[s->transp][s->bpp];
56
+ drawfn fn = pxa2xx_drawfn(s);
57
if (!fn)
58
return;
59
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
139
--
164
--
140
2.20.1
165
2.20.1
141
166
142
167
diff view generated by jsdifflib
1
Correct a typo in the name we give the NVIC object.
1
Since the dest_width is now always 4 because the output surface is
2
32bpp, we can replace the dest_width state field with a constant.
2
3
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210211141515.8755-6-peter.maydell@linaro.org
6
Message-id: 20201119215617.29887-28-peter.maydell@linaro.org
7
---
7
---
8
hw/arm/armv7m.c | 2 +-
8
hw/display/pxa2xx_lcd.c | 20 +++++++++++---------
9
1 file changed, 1 insertion(+), 1 deletion(-)
9
1 file changed, 11 insertions(+), 9 deletions(-)
10
10
11
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
11
diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c
12
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/armv7m.c
13
--- a/hw/display/pxa2xx_lcd.c
14
+++ b/hw/arm/armv7m.c
14
+++ b/hw/display/pxa2xx_lcd.c
15
@@ -XXX,XX +XXX,XX @@ static void armv7m_instance_init(Object *obj)
15
@@ -XXX,XX +XXX,XX @@ typedef struct QEMU_PACKED {
16
16
#define LDCMD_SOFINT    (1 << 22)
17
memory_region_init(&s->container, obj, "armv7m-container", UINT64_MAX);
17
#define LDCMD_PAL    (1 << 26)
18
18
19
- object_initialize_child(obj, "nvnic", &s->nvic, TYPE_NVIC);
19
+/* Size of a pixel in the QEMU UI output surface, in bytes */
20
+ object_initialize_child(obj, "nvic", &s->nvic, TYPE_NVIC);
20
+#define DEST_PIXEL_WIDTH 4
21
object_property_add_alias(obj, "num-irq",
21
+
22
OBJECT(&s->nvic), "num-irq");
22
#define BITS 32
23
#include "pxa2xx_template.h"
24
25
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
26
else if (s->bpp > pxa_lcdc_8bpp)
27
src_width *= 2;
28
29
- dest_width = s->xres * s->dest_width;
30
+ dest_width = s->xres * DEST_PIXEL_WIDTH;
31
*miny = 0;
32
if (s->invalidated) {
33
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
34
addr, s->yres, src_width);
35
}
36
framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
37
- src_width, dest_width, s->dest_width,
38
+ src_width, dest_width, DEST_PIXEL_WIDTH,
39
s->invalidated,
40
fn, s->dma_ch[0].palette, miny, maxy);
41
}
42
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
43
else if (s->bpp > pxa_lcdc_8bpp)
44
src_width *= 2;
45
46
- dest_width = s->yres * s->dest_width;
47
+ dest_width = s->yres * DEST_PIXEL_WIDTH;
48
*miny = 0;
49
if (s->invalidated) {
50
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
51
addr, s->yres, src_width);
52
}
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);
23
100
24
--
101
--
25
2.20.1
102
2.20.1
26
103
27
104
diff view generated by jsdifflib
1
For M-profile CPUs, the range from 0xe0000000 to 0xe00fffff is the
1
Now that BITS is always 32, expand out all its uses in the template
2
Private Peripheral Bus range, which includes all of the memory mapped
2
header, including removing now-useless uses of the glue() macro.
3
devices and registers that are part of the CPU itself, including the
4
NVIC, systick timer, and debug and trace components like the Data
5
Watchpoint and Trace unit (DWT). Within this large region, the range
6
0xe000e000 to 0xe000efff is the System Control Space (NVIC, system
7
registers, systick) and 0xe002e000 to 0exe002efff is its Non-secure
8
alias.
9
10
The architecture is clear that within the SCS unimplemented registers
11
should be RES0 for privileged accesses and generate BusFault for
12
unprivileged accesses, and we currently implement this.
13
14
It is less clear about how to handle accesses to unimplemented
15
regions of the wider PPB. Unprivileged accesses should definitely
16
cause BusFaults (R_DQQS), but the behaviour of privileged accesses is
17
not given as a general rule. However, the register definitions of
18
individual registers for components like the DWT all state that they
19
are RES0 if the relevant component is not implemented, so the
20
simplest way to provide that is to provide RAZ/WI for the whole range
21
for privileged accesses. (The v7M Arm ARM does say that reserved
22
registers should be UNK/SBZP.)
23
24
Expand the container MemoryRegion that the NVIC exposes so that
25
it covers the whole PPB space. This means:
26
* moving the address that the ARMV7M device maps it to down by
27
0xe000 bytes
28
* moving the off and the offsets within the container of all the
29
subregions forward by 0xe000 bytes
30
* adding a new default MemoryRegion that covers the whole container
31
at a lower priority than anything else and which provides the
32
RAZWI/BusFault behaviour
33
3
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
35
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
36
Message-id: 20201119215617.29887-2-peter.maydell@linaro.org
6
Message-id: 20210211141515.8755-7-peter.maydell@linaro.org
37
---
7
---
38
include/hw/intc/armv7m_nvic.h | 1 +
8
hw/display/pxa2xx_template.h | 110 ++++++++++++++---------------------
39
hw/arm/armv7m.c | 2 +-
9
1 file changed, 45 insertions(+), 65 deletions(-)
40
hw/intc/armv7m_nvic.c | 78 ++++++++++++++++++++++++++++++-----
41
3 files changed, 69 insertions(+), 12 deletions(-)
42
10
43
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
11
diff --git a/hw/display/pxa2xx_template.h b/hw/display/pxa2xx_template.h
44
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
45
--- a/include/hw/intc/armv7m_nvic.h
13
--- a/hw/display/pxa2xx_template.h
46
+++ b/include/hw/intc/armv7m_nvic.h
14
+++ b/hw/display/pxa2xx_template.h
47
@@ -XXX,XX +XXX,XX @@ struct NVICState {
15
@@ -XXX,XX +XXX,XX @@
48
MemoryRegion systickmem;
16
*/
49
MemoryRegion systick_ns_mem;
17
50
MemoryRegion container;
18
# define SKIP_PIXEL(to)        to += deststep
51
+ MemoryRegion defaultmem;
19
-#if BITS == 8
52
20
-# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0)
53
uint32_t num_irq;
21
-#elif BITS == 15 || BITS == 16
54
qemu_irq excpout;
22
-# define COPY_PIXEL(to, from) \
55
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
23
- do { \
56
index XXXXXXX..XXXXXXX 100644
24
- *(uint16_t *) to = from; \
57
--- a/hw/arm/armv7m.c
25
- SKIP_PIXEL(to); \
58
+++ b/hw/arm/armv7m.c
26
- } while (0)
59
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
27
-#elif BITS == 24
60
sysbus_connect_irq(sbd, 0,
28
-# define COPY_PIXEL(to, from) \
61
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
29
- do { \
62
30
- *(uint16_t *) to = from; \
63
- memory_region_add_subregion(&s->container, 0xe000e000,
31
- *(to + 2) = (from) >> 16; \
64
+ memory_region_add_subregion(&s->container, 0xe0000000,
32
- SKIP_PIXEL(to); \
65
sysbus_mmio_get_region(sbd, 0));
33
- } while (0)
66
34
-#elif BITS == 32
67
for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
35
# define COPY_PIXEL(to, from) \
68
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
36
do { \
69
index XXXXXXX..XXXXXXX 100644
37
*(uint32_t *) to = from; \
70
--- a/hw/intc/armv7m_nvic.c
38
SKIP_PIXEL(to); \
71
+++ b/hw/intc/armv7m_nvic.c
39
} while (0)
72
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
40
-#else
73
.endianness = DEVICE_NATIVE_ENDIAN,
41
-# error unknown bit depth
42
-#endif
43
44
#ifdef HOST_WORDS_BIGENDIAN
45
# define SWAP_WORDS    1
46
@@ -XXX,XX +XXX,XX @@
47
#define FN_2(x)        FN(x + 1) FN(x)
48
#define FN_4(x)        FN_2(x + 2) FN_2(x)
49
50
-static void glue(pxa2xx_draw_line2_, BITS)(void *opaque,
51
+static void pxa2xx_draw_line2(void *opaque,
52
uint8_t *dest, const uint8_t *src, int width, int deststep)
53
{
54
uint32_t *palette = opaque;
55
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line2_, BITS)(void *opaque,
56
}
57
}
58
59
-static void glue(pxa2xx_draw_line4_, BITS)(void *opaque,
60
+static void pxa2xx_draw_line4(void *opaque,
61
uint8_t *dest, const uint8_t *src, int width, int deststep)
62
{
63
uint32_t *palette = opaque;
64
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line4_, BITS)(void *opaque,
65
}
66
}
67
68
-static void glue(pxa2xx_draw_line8_, BITS)(void *opaque,
69
+static void pxa2xx_draw_line8(void *opaque,
70
uint8_t *dest, const uint8_t *src, int width, int deststep)
71
{
72
uint32_t *palette = opaque;
73
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line8_, BITS)(void *opaque,
74
}
75
}
76
77
-static void glue(pxa2xx_draw_line16_, BITS)(void *opaque,
78
+static void pxa2xx_draw_line16(void *opaque,
79
uint8_t *dest, const uint8_t *src, int width, int deststep)
80
{
81
uint32_t data;
82
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line16_, BITS)(void *opaque,
83
data >>= 6;
84
r = (data & 0x1f) << 3;
85
data >>= 5;
86
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
87
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
88
b = (data & 0x1f) << 3;
89
data >>= 5;
90
g = (data & 0x3f) << 2;
91
data >>= 6;
92
r = (data & 0x1f) << 3;
93
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
94
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
95
width -= 2;
96
src += 4;
97
}
98
}
99
100
-static void glue(pxa2xx_draw_line16t_, BITS)(void *opaque,
101
+static void pxa2xx_draw_line16t(void *opaque,
102
uint8_t *dest, const uint8_t *src, int width, int deststep)
103
{
104
uint32_t data;
105
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line16t_, BITS)(void *opaque,
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,
74
};
306
};
75
307
76
+/*
308
/* Overlay planes enabled, transparency used */
77
+ * Unassigned portions of the PPB space are RAZ/WI for privileged
309
-static drawfn glue(glue(pxa2xx_draw_fn_, BITS), t)[16] =
78
+ * accesses, and fault for non-privileged accesses.
310
+static drawfn pxa2xx_draw_fn_32t[16] =
79
+ */
311
{
80
+static MemTxResult ppb_default_read(void *opaque, hwaddr addr,
312
[0 ... 0xf] = NULL,
81
+ uint64_t *data, unsigned size,
313
- [pxa_lcdc_4bpp] = glue(pxa2xx_draw_line4_, BITS),
82
+ MemTxAttrs attrs)
314
- [pxa_lcdc_8bpp] = glue(pxa2xx_draw_line8_, BITS),
83
+{
315
- [pxa_lcdc_16bpp] = glue(pxa2xx_draw_line16t_, BITS),
84
+ qemu_log_mask(LOG_UNIMP, "Read of unassigned area of PPB: offset 0x%x\n",
316
- [pxa_lcdc_19bpp] = glue(pxa2xx_draw_line19_, BITS),
85
+ (uint32_t)addr);
317
- [pxa_lcdc_19pbpp] = glue(pxa2xx_draw_line19p_, BITS),
86
+ if (attrs.user) {
318
- [pxa_lcdc_24bpp] = glue(pxa2xx_draw_line24t_, BITS),
87
+ return MEMTX_ERROR;
319
- [pxa_lcdc_25bpp] = glue(pxa2xx_draw_line25_, BITS),
88
+ }
320
+ [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
89
+ *data = 0;
321
+ [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
90
+ return MEMTX_OK;
322
+ [pxa_lcdc_16bpp] = pxa2xx_draw_line16t,
91
+}
323
+ [pxa_lcdc_19bpp] = pxa2xx_draw_line19,
92
+
324
+ [pxa_lcdc_19pbpp] = pxa2xx_draw_line19p,
93
+static MemTxResult ppb_default_write(void *opaque, hwaddr addr,
325
+ [pxa_lcdc_24bpp] = pxa2xx_draw_line24t,
94
+ uint64_t value, unsigned size,
326
+ [pxa_lcdc_25bpp] = pxa2xx_draw_line25,
95
+ MemTxAttrs attrs)
327
};
96
+{
328
97
+ qemu_log_mask(LOG_UNIMP, "Write of unassigned area of PPB: offset 0x%x\n",
329
-#undef BITS
98
+ (uint32_t)addr);
330
#undef COPY_PIXEL
99
+ if (attrs.user) {
331
#undef SKIP_PIXEL
100
+ return MEMTX_ERROR;
101
+ }
102
+ return MEMTX_OK;
103
+}
104
+
105
+static const MemoryRegionOps ppb_default_ops = {
106
+ .read_with_attrs = ppb_default_read,
107
+ .write_with_attrs = ppb_default_write,
108
+ .endianness = DEVICE_NATIVE_ENDIAN,
109
+ .valid.min_access_size = 1,
110
+ .valid.max_access_size = 8,
111
+};
112
+
113
static int nvic_post_load(void *opaque, int version_id)
114
{
115
NVICState *s = opaque;
116
@@ -XXX,XX +XXX,XX @@ static void nvic_systick_trigger(void *opaque, int n, int level)
117
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
118
{
119
NVICState *s = NVIC(dev);
120
- int regionlen;
121
122
/* The armv7m container object will have set our CPU pointer */
123
if (!s->cpu || !arm_feature(&s->cpu->env, ARM_FEATURE_M)) {
124
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
125
M_REG_S));
126
}
127
128
- /* The NVIC and System Control Space (SCS) starts at 0xe000e000
129
+ /*
130
+ * This device provides a single sysbus memory region which
131
+ * represents the whole of the "System PPB" space. This is the
132
+ * range from 0xe0000000 to 0xe00fffff and includes the NVIC,
133
+ * the System Control Space (system registers), the systick timer,
134
+ * and for CPUs with the Security extension an NS banked version
135
+ * of all of these.
136
+ *
137
+ * The default behaviour for unimplemented registers/ranges
138
+ * (for instance the Data Watchpoint and Trace unit at 0xe0001000)
139
+ * is to RAZ/WI for privileged access and BusFault for non-privileged
140
+ * access.
141
+ *
142
+ * The NVIC and System Control Space (SCS) starts at 0xe000e000
143
* and looks like this:
144
* 0x004 - ICTR
145
* 0x010 - 0xff - systick
146
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
147
* generally code determining which banked register to use should
148
* use attrs.secure; code determining actual behaviour of the system
149
* should use env->v7m.secure.
150
+ *
151
+ * The container covers the whole PPB space. Within it the priority
152
+ * of overlapping regions is:
153
+ * - default region (for RAZ/WI and BusFault) : -1
154
+ * - system register regions : 0
155
+ * - systick : 1
156
+ * This is because the systick device is a small block of registers
157
+ * in the middle of the other system control registers.
158
*/
159
- regionlen = arm_feature(&s->cpu->env, ARM_FEATURE_V8) ? 0x21000 : 0x1000;
160
- memory_region_init(&s->container, OBJECT(s), "nvic", regionlen);
161
- /* The system register region goes at the bottom of the priority
162
- * stack as it covers the whole page.
163
- */
164
+ memory_region_init(&s->container, OBJECT(s), "nvic", 0x100000);
165
+ memory_region_init_io(&s->defaultmem, OBJECT(s), &ppb_default_ops, s,
166
+ "nvic-default", 0x100000);
167
+ memory_region_add_subregion_overlap(&s->container, 0, &s->defaultmem, -1);
168
memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s,
169
"nvic_sysregs", 0x1000);
170
- memory_region_add_subregion(&s->container, 0, &s->sysregmem);
171
+ memory_region_add_subregion(&s->container, 0xe000, &s->sysregmem);
172
173
memory_region_init_io(&s->systickmem, OBJECT(s),
174
&nvic_systick_ops, s,
175
"nvic_systick", 0xe0);
176
177
- memory_region_add_subregion_overlap(&s->container, 0x10,
178
+ memory_region_add_subregion_overlap(&s->container, 0xe010,
179
&s->systickmem, 1);
180
181
if (arm_feature(&s->cpu->env, ARM_FEATURE_V8)) {
182
memory_region_init_io(&s->sysreg_ns_mem, OBJECT(s),
183
&nvic_sysreg_ns_ops, &s->sysregmem,
184
"nvic_sysregs_ns", 0x1000);
185
- memory_region_add_subregion(&s->container, 0x20000, &s->sysreg_ns_mem);
186
+ memory_region_add_subregion(&s->container, 0x2e000, &s->sysreg_ns_mem);
187
memory_region_init_io(&s->systick_ns_mem, OBJECT(s),
188
&nvic_sysreg_ns_ops, &s->systickmem,
189
"nvic_systick_ns", 0xe0);
190
- memory_region_add_subregion_overlap(&s->container, 0x20010,
191
+ memory_region_add_subregion_overlap(&s->container, 0x2e010,
192
&s->systick_ns_mem, 1);
193
}
194
332
195
--
333
--
196
2.20.1
334
2.20.1
197
335
198
336
diff view generated by jsdifflib
1
Implement the new-in-v8.1M FPCXT_S floating point system register.
1
We're about to move code from the template header into pxa2xx_lcd.c.
2
This is for saving and restoring the secure floating point context,
2
Before doing that, make coding style fixes so checkpatch doesn't
3
and it reads and writes bits [27:0] from the FPSCR and the
3
complain about the patch which moves the code. This commit fixes
4
CONTROL.SFPA bit in bit [31].
4
missing braces in the SKIP_PIXEL() macro definition and in if()
5
statements.
5
6
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
8
Message-id: 20201119215617.29887-14-peter.maydell@linaro.org
9
Message-id: 20210211141515.8755-8-peter.maydell@linaro.org
9
---
10
---
10
target/arm/translate-vfp.c.inc | 58 ++++++++++++++++++++++++++++++++++
11
hw/display/pxa2xx_template.h | 47 +++++++++++++++++++++---------------
11
1 file changed, 58 insertions(+)
12
1 file changed, 28 insertions(+), 19 deletions(-)
12
13
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
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/target/arm/translate-vfp.c.inc
16
--- a/hw/display/pxa2xx_template.h
16
+++ b/target/arm/translate-vfp.c.inc
17
+++ b/hw/display/pxa2xx_template.h
17
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
18
@@ -XXX,XX +XXX,XX @@
18
return false;
19
* Framebuffer format conversion routines.
19
}
20
*/
20
break;
21
21
+ case ARM_VFP_FPCXT_S:
22
-# define SKIP_PIXEL(to)        to += deststep
22
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
23
+# define SKIP_PIXEL(to) do { to += deststep; } while (0)
23
+ return false;
24
# define COPY_PIXEL(to, from) \
25
do { \
26
*(uint32_t *) to = from; \
27
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line16t(void *opaque,
28
data >>= 5;
29
r = (data & 0x1f) << 3;
30
data >>= 5;
31
- if (data & 1)
32
+ if (data & 1) {
33
SKIP_PIXEL(dest);
34
- else
35
+ } else {
36
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
24
+ }
37
+ }
25
+ if (!s->v8m_secure) {
38
data >>= 1;
26
+ return false;
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));
27
+ }
51
+ }
28
+ break;
52
width -= 2;
29
default:
53
src += 4;
30
return FPSysRegCheckFailed;
31
}
54
}
32
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
55
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19(void *opaque,
33
tcg_temp_free_i32(tmp);
56
data >>= 6;
34
break;
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;
35
}
68
}
36
+ case ARM_VFP_FPCXT_S:
69
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19p(void *opaque,
37
+ {
70
data[0] >>= 6;
38
+ TCGv_i32 sfpa, control, fpscr;
71
r = (data[0] & 0x3f) << 2;
39
+ /* Set FPSCR[27:0] and CONTROL.SFPA from value */
72
data[0] >>= 6;
40
+ tmp = loadfn(s, opaque);
73
- if (data[0] & 1)
41
+ sfpa = tcg_temp_new_i32();
74
+ if (data[0] & 1) {
42
+ tcg_gen_shri_i32(sfpa, tmp, 31);
75
SKIP_PIXEL(dest);
43
+ control = load_cpu_field(v7m.control[M_REG_S]);
76
- else
44
+ tcg_gen_deposit_i32(control, control, sfpa,
77
+ } else {
45
+ R_V7M_CONTROL_SFPA_SHIFT, 1);
78
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
46
+ store_cpu_field(control, v7m.control[M_REG_S]);
79
+ }
47
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
80
data[0] >>= 6;
48
+ tcg_gen_andi_i32(fpscr, fpscr, FPCR_NZCV_MASK);
81
b = (data[0] & 0x3f) << 2;
49
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
82
data[0] >>= 6;
50
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
83
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19p(void *opaque,
51
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
84
data[1] >>= 4;
52
+ tcg_temp_free_i32(tmp);
85
r = (data[1] & 0x3f) << 2;
53
+ tcg_temp_free_i32(sfpa);
86
data[1] >>= 6;
54
+ break;
87
- if (data[1] & 1)
55
+ }
88
+ if (data[1] & 1) {
56
default:
89
SKIP_PIXEL(dest);
57
g_assert_not_reached();
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;
58
}
123
}
59
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
124
}
60
tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
125
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line24t(void *opaque,
61
storefn(s, opaque, tmp);
126
data >>= 8;
62
break;
127
r = data & 0xff;
63
+ case ARM_VFP_FPCXT_S:
128
data >>= 8;
64
+ {
129
- if (data & 1)
65
+ TCGv_i32 control, sfpa, fpscr;
130
+ if (data & 1) {
66
+ /* Bits [27:0] from FPSCR, bit [31] from CONTROL.SFPA */
131
SKIP_PIXEL(dest);
67
+ tmp = tcg_temp_new_i32();
132
- else
68
+ sfpa = tcg_temp_new_i32();
133
+ } else {
69
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
134
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
70
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
135
+ }
71
+ control = load_cpu_field(v7m.control[M_REG_S]);
136
width -= 1;
72
+ tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
137
src += 4;
73
+ tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
138
}
74
+ tcg_gen_or_i32(tmp, tmp, sfpa);
139
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line25(void *opaque,
75
+ tcg_temp_free_i32(sfpa);
140
data >>= 8;
76
+ /*
141
r = data & 0xff;
77
+ * Store result before updating FPSCR etc, in case
142
data >>= 8;
78
+ * it is a memory write which causes an exception.
143
- if (data & 1)
79
+ */
144
+ if (data & 1) {
80
+ storefn(s, opaque, tmp);
145
SKIP_PIXEL(dest);
81
+ /*
146
- else
82
+ * Now we must reset FPSCR from FPDSCR_NS, and clear
147
+ } else {
83
+ * CONTROL.SFPA; so we'll end the TB here.
148
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
84
+ */
149
+ }
85
+ tcg_gen_andi_i32(control, control, ~R_V7M_CONTROL_SFPA_MASK);
150
width -= 1;
86
+ store_cpu_field(control, v7m.control[M_REG_S]);
151
src += 4;
87
+ fpscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
88
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
89
+ tcg_temp_free_i32(fpscr);
90
+ gen_lookup_tb(s);
91
+ break;
92
+ }
93
default:
94
g_assert_not_reached();
95
}
152
}
96
--
153
--
97
2.20.1
154
2.20.1
98
155
99
156
diff view generated by jsdifflib
1
v8.1M defines a new FP system register FPSCR_nzcvqc; this behaves
1
We're about to move code from the template header into pxa2xx_lcd.c.
2
like the existing FPSCR, except that it reads and writes only bits
2
Before doing that, make coding style fixes so checkpatch doesn't
3
[31:27] of the FPSCR (the N, Z, C, V and QC flag bits). (Unlike the
3
complain about the patch which moves the code. This commit is
4
FPSCR, the special case for Rt=15 of writing the CPSR.NZCV is not
4
whitespace changes only:
5
permitted.)
5
* avoid hard-coded tabs
6
6
* fix ident on function prototypes
7
Implement the register. Since we don't yet implement MVE, we handle
7
* no newline before open brace on array definitions
8
the QC bit as RES0, with todo comments for where we will need to add
9
support later.
10
8
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
13
Message-id: 20201119215617.29887-11-peter.maydell@linaro.org
11
Message-id: 20210211141515.8755-9-peter.maydell@linaro.org
14
---
12
---
15
target/arm/cpu.h | 13 +++++++++++++
13
hw/display/pxa2xx_template.h | 66 +++++++++++++++++-------------------
16
target/arm/translate-vfp.c.inc | 27 +++++++++++++++++++++++++++
14
1 file changed, 32 insertions(+), 34 deletions(-)
17
2 files changed, 40 insertions(+)
15
18
16
diff --git a/hw/display/pxa2xx_template.h b/hw/display/pxa2xx_template.h
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
18
--- a/hw/display/pxa2xx_template.h
22
+++ b/target/arm/cpu.h
19
+++ b/hw/display/pxa2xx_template.h
23
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
20
@@ -XXX,XX +XXX,XX @@
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
21
} while (0)
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
22
26
#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
23
#ifdef HOST_WORDS_BIGENDIAN
27
+#define FPCR_V (1 << 28) /* FP overflow flag */
24
-# define SWAP_WORDS    1
28
+#define FPCR_C (1 << 29) /* FP carry flag */
25
+# define SWAP_WORDS 1
29
+#define FPCR_Z (1 << 30) /* FP zero flag */
26
#endif
30
+#define FPCR_N (1 << 31) /* FP negative flag */
27
31
+
28
-#define FN_2(x)        FN(x + 1) FN(x)
32
+#define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
29
-#define FN_4(x)        FN_2(x + 2) FN_2(x)
33
+#define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
30
+#define FN_2(x) FN(x + 1) FN(x)
34
31
+#define FN_4(x) FN_2(x + 2) FN_2(x)
35
static inline uint32_t vfp_get_fpsr(CPUARMState *env)
32
36
{
33
-static void pxa2xx_draw_line2(void *opaque,
37
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
34
- uint8_t *dest, const uint8_t *src, int width, int deststep)
38
#define ARM_VFP_FPEXC 8
35
+static void pxa2xx_draw_line2(void *opaque, uint8_t *dest, const uint8_t *src,
39
#define ARM_VFP_FPINST 9
36
+ int width, int deststep)
40
#define ARM_VFP_FPINST2 10
37
{
41
+/* These ones are M-profile only */
38
uint32_t *palette = opaque;
42
+#define ARM_VFP_FPSCR_NZCVQC 2
39
uint32_t data;
43
+#define ARM_VFP_VPR 12
40
while (width > 0) {
44
+#define ARM_VFP_P0 13
41
data = *(uint32_t *) src;
45
+#define ARM_VFP_FPCXT_NS 14
42
-#define FN(x)        COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
46
+#define ARM_VFP_FPCXT_S 15
43
+#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
47
44
#ifdef SWAP_WORDS
48
/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
45
FN_4(12)
49
#define QEMU_VFP_FPSCR_NZCV 0xffff
46
FN_4(8)
50
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
47
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line2(void *opaque,
51
index XXXXXXX..XXXXXXX 100644
48
}
52
--- a/target/arm/translate-vfp.c.inc
49
}
53
+++ b/target/arm/translate-vfp.c.inc
50
54
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
51
-static void pxa2xx_draw_line4(void *opaque,
55
case ARM_VFP_FPSCR:
52
- uint8_t *dest, const uint8_t *src, int width, int deststep)
56
case QEMU_VFP_FPSCR_NZCV:
53
+static void pxa2xx_draw_line4(void *opaque, uint8_t *dest, const uint8_t *src,
57
break;
54
+ int width, int deststep)
58
+ case ARM_VFP_FPSCR_NZCVQC:
55
{
59
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
56
uint32_t *palette = opaque;
60
+ return false;
57
uint32_t data;
61
+ }
58
while (width > 0) {
62
+ break;
59
data = *(uint32_t *) src;
63
default:
60
-#define FN(x)        COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
64
return FPSysRegCheckFailed;
61
+#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
65
}
62
#ifdef SWAP_WORDS
66
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
63
FN_2(6)
67
tcg_temp_free_i32(tmp);
64
FN_2(4)
68
gen_lookup_tb(s);
65
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line4(void *opaque,
69
break;
66
}
70
+ case ARM_VFP_FPSCR_NZCVQC:
67
}
71
+ {
68
72
+ TCGv_i32 fpscr;
69
-static void pxa2xx_draw_line8(void *opaque,
73
+ tmp = loadfn(s, opaque);
70
- uint8_t *dest, const uint8_t *src, int width, int deststep)
74
+ /*
71
+static void pxa2xx_draw_line8(void *opaque, uint8_t *dest, const uint8_t *src,
75
+ * TODO: when we implement MVE, write the QC bit.
72
+ int width, int deststep)
76
+ * For non-MVE, QC is RES0.
73
{
77
+ */
74
uint32_t *palette = opaque;
78
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
75
uint32_t data;
79
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
76
while (width > 0) {
80
+ tcg_gen_andi_i32(fpscr, fpscr, ~FPCR_NZCV_MASK);
77
data = *(uint32_t *) src;
81
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
78
-#define FN(x)        COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
82
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
79
+#define FN(x) COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
83
+ tcg_temp_free_i32(tmp);
80
#ifdef SWAP_WORDS
84
+ break;
81
FN(24)
85
+ }
82
FN(16)
86
default:
83
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line8(void *opaque,
87
g_assert_not_reached();
84
}
88
}
85
}
89
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
86
90
gen_helper_vfp_get_fpscr(tmp, cpu_env);
87
-static void pxa2xx_draw_line16(void *opaque,
91
storefn(s, opaque, tmp);
88
- uint8_t *dest, const uint8_t *src, int width, int deststep)
92
break;
89
+static void pxa2xx_draw_line16(void *opaque, uint8_t *dest, const uint8_t *src,
93
+ case ARM_VFP_FPSCR_NZCVQC:
90
+ int width, int deststep)
94
+ /*
91
{
95
+ * TODO: MVE has a QC bit, which we probably won't store
92
uint32_t data;
96
+ * in the xregs[] field. For non-MVE, where QC is RES0,
93
unsigned int r, g, b;
97
+ * we can just fall through to the FPSCR_NZCV case.
94
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line16(void *opaque,
98
+ */
95
}
99
case QEMU_VFP_FPSCR_NZCV:
96
}
100
/*
97
101
* Read just NZCV; this is a special case to avoid the
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,
102
--
202
--
103
2.20.1
203
2.20.1
104
204
105
205
diff view generated by jsdifflib
1
In v8.1M the PXN architecture extension adds a new PXN bit to the
1
The template header is now included only once; just inline its contents
2
MPU_RLAR registers, which forbids execution of code in the region
2
in hw/display/pxa2xx_lcd.c.
3
from a privileged mode.
4
5
This is another feature which is just in the generic "in v8.1M" set
6
and has no ID register field indicating its presence.
7
3
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
10
Message-id: 20201119215617.29887-3-peter.maydell@linaro.org
6
Message-id: 20210211141515.8755-10-peter.maydell@linaro.org
11
---
7
---
12
target/arm/helper.c | 7 ++++++-
8
hw/display/pxa2xx_template.h | 434 -----------------------------------
13
1 file changed, 6 insertions(+), 1 deletion(-)
9
hw/display/pxa2xx_lcd.c | 427 +++++++++++++++++++++++++++++++++-
10
2 files changed, 425 insertions(+), 436 deletions(-)
11
delete mode 100644 hw/display/pxa2xx_template.h
14
12
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
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
16
index XXXXXXX..XXXXXXX 100644
454
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
455
--- a/hw/display/pxa2xx_lcd.c
18
+++ b/target/arm/helper.c
456
+++ b/hw/display/pxa2xx_lcd.c
19
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
457
@@ -XXX,XX +XXX,XX @@ typedef struct QEMU_PACKED {
20
} else {
458
/* Size of a pixel in the QEMU UI output surface, in bytes */
21
uint32_t ap = extract32(env->pmsav8.rbar[secure][matchregion], 1, 2);
459
#define DEST_PIXEL_WIDTH 4
22
uint32_t xn = extract32(env->pmsav8.rbar[secure][matchregion], 0, 1);
460
23
+ bool pxn = false;
461
-#define BITS 32
24
+
462
-#include "pxa2xx_template.h"
25
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
463
+/* Line drawing code to handle the various possible guest pixel formats */
26
+ pxn = extract32(env->pmsav8.rlar[secure][matchregion], 4, 1);
464
+
465
+# define SKIP_PIXEL(to) do { to += deststep; } while (0)
466
+# define COPY_PIXEL(to, from) \
467
+ do { \
468
+ *(uint32_t *) to = from; \
469
+ SKIP_PIXEL(to); \
470
+ } while (0)
471
+
472
+#ifdef HOST_WORDS_BIGENDIAN
473
+# define SWAP_WORDS 1
474
+#endif
475
+
476
+#define FN_2(x) FN(x + 1) FN(x)
477
+#define FN_4(x) FN_2(x + 2) FN_2(x)
478
+
479
+static void pxa2xx_draw_line2(void *opaque, uint8_t *dest, const uint8_t *src,
480
+ int width, int deststep)
481
+{
482
+ uint32_t *palette = opaque;
483
+ uint32_t data;
484
+ while (width > 0) {
485
+ data = *(uint32_t *) src;
486
+#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
487
+#ifdef SWAP_WORDS
488
+ FN_4(12)
489
+ FN_4(8)
490
+ FN_4(4)
491
+ FN_4(0)
492
+#else
493
+ FN_4(0)
494
+ FN_4(4)
495
+ FN_4(8)
496
+ FN_4(12)
497
+#endif
498
+#undef FN
499
+ width -= 16;
500
+ src += 4;
501
+ }
502
+}
503
+
504
+static void pxa2xx_draw_line4(void *opaque, uint8_t *dest, const uint8_t *src,
505
+ int width, int deststep)
506
+{
507
+ uint32_t *palette = opaque;
508
+ uint32_t data;
509
+ while (width > 0) {
510
+ data = *(uint32_t *) src;
511
+#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
512
+#ifdef SWAP_WORDS
513
+ FN_2(6)
514
+ FN_2(4)
515
+ FN_2(2)
516
+ FN_2(0)
517
+#else
518
+ FN_2(0)
519
+ FN_2(2)
520
+ FN_2(4)
521
+ FN_2(6)
522
+#endif
523
+#undef FN
524
+ width -= 8;
525
+ src += 4;
526
+ }
527
+}
528
+
529
+static void pxa2xx_draw_line8(void *opaque, uint8_t *dest, const uint8_t *src,
530
+ int width, int deststep)
531
+{
532
+ uint32_t *palette = opaque;
533
+ uint32_t data;
534
+ while (width > 0) {
535
+ data = *(uint32_t *) src;
536
+#define FN(x) COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
537
+#ifdef SWAP_WORDS
538
+ FN(24)
539
+ FN(16)
540
+ FN(8)
541
+ FN(0)
542
+#else
543
+ FN(0)
544
+ FN(8)
545
+ FN(16)
546
+ FN(24)
547
+#endif
548
+#undef FN
549
+ width -= 4;
550
+ src += 4;
551
+ }
552
+}
553
+
554
+static void pxa2xx_draw_line16(void *opaque, uint8_t *dest, const uint8_t *src,
555
+ int width, int deststep)
556
+{
557
+ uint32_t data;
558
+ unsigned int r, g, b;
559
+ while (width > 0) {
560
+ data = *(uint32_t *) src;
561
+#ifdef SWAP_WORDS
562
+ data = bswap32(data);
563
+#endif
564
+ b = (data & 0x1f) << 3;
565
+ data >>= 5;
566
+ g = (data & 0x3f) << 2;
567
+ data >>= 6;
568
+ r = (data & 0x1f) << 3;
569
+ data >>= 5;
570
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
571
+ b = (data & 0x1f) << 3;
572
+ data >>= 5;
573
+ g = (data & 0x3f) << 2;
574
+ data >>= 6;
575
+ r = (data & 0x1f) << 3;
576
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
577
+ width -= 2;
578
+ src += 4;
579
+ }
580
+}
581
+
582
+static void pxa2xx_draw_line16t(void *opaque, uint8_t *dest, const uint8_t *src,
583
+ int width, int deststep)
584
+{
585
+ uint32_t data;
586
+ unsigned int r, g, b;
587
+ while (width > 0) {
588
+ data = *(uint32_t *) src;
589
+#ifdef SWAP_WORDS
590
+ data = bswap32(data);
591
+#endif
592
+ b = (data & 0x1f) << 3;
593
+ data >>= 5;
594
+ g = (data & 0x1f) << 3;
595
+ data >>= 5;
596
+ r = (data & 0x1f) << 3;
597
+ data >>= 5;
598
+ if (data & 1) {
599
+ SKIP_PIXEL(dest);
600
+ } else {
601
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
27
+ }
602
+ }
28
603
+ data >>= 1;
29
if (m_is_system_region(env, address)) {
604
+ b = (data & 0x1f) << 3;
30
/* System space is always execute never */
605
+ data >>= 5;
31
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
606
+ g = (data & 0x1f) << 3;
32
}
607
+ data >>= 5;
33
608
+ r = (data & 0x1f) << 3;
34
*prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
609
+ data >>= 5;
35
- if (*prot && !xn) {
610
+ if (data & 1) {
36
+ if (*prot && !xn && !(pxn && !is_user)) {
611
+ SKIP_PIXEL(dest);
37
*prot |= PAGE_EXEC;
612
+ } else {
38
}
613
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
39
/* We don't need to look the attribute up in the MAIR0/MAIR1
614
+ }
615
+ width -= 2;
616
+ src += 4;
617
+ }
618
+}
619
+
620
+static void pxa2xx_draw_line18(void *opaque, uint8_t *dest, const uint8_t *src,
621
+ int width, int deststep)
622
+{
623
+ uint32_t data;
624
+ unsigned int r, g, b;
625
+ while (width > 0) {
626
+ data = *(uint32_t *) src;
627
+#ifdef SWAP_WORDS
628
+ data = bswap32(data);
629
+#endif
630
+ b = (data & 0x3f) << 2;
631
+ data >>= 6;
632
+ g = (data & 0x3f) << 2;
633
+ data >>= 6;
634
+ r = (data & 0x3f) << 2;
635
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
636
+ width -= 1;
637
+ src += 4;
638
+ }
639
+}
640
+
641
+/* The wicked packed format */
642
+static void pxa2xx_draw_line18p(void *opaque, uint8_t *dest, const uint8_t *src,
643
+ int width, int deststep)
644
+{
645
+ uint32_t data[3];
646
+ unsigned int r, g, b;
647
+ while (width > 0) {
648
+ data[0] = *(uint32_t *) src;
649
+ src += 4;
650
+ data[1] = *(uint32_t *) src;
651
+ src += 4;
652
+ data[2] = *(uint32_t *) src;
653
+ src += 4;
654
+#ifdef SWAP_WORDS
655
+ data[0] = bswap32(data[0]);
656
+ data[1] = bswap32(data[1]);
657
+ data[2] = bswap32(data[2]);
658
+#endif
659
+ b = (data[0] & 0x3f) << 2;
660
+ data[0] >>= 6;
661
+ g = (data[0] & 0x3f) << 2;
662
+ data[0] >>= 6;
663
+ r = (data[0] & 0x3f) << 2;
664
+ data[0] >>= 12;
665
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
666
+ b = (data[0] & 0x3f) << 2;
667
+ data[0] >>= 6;
668
+ g = ((data[1] & 0xf) << 4) | (data[0] << 2);
669
+ data[1] >>= 4;
670
+ r = (data[1] & 0x3f) << 2;
671
+ data[1] >>= 12;
672
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
673
+ b = (data[1] & 0x3f) << 2;
674
+ data[1] >>= 6;
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,
868
+};
869
+
870
+/* Overlay planes enabled, transparency used */
871
+static drawfn pxa2xx_draw_fn_32t[16] = {
872
+ [0 ... 0xf] = NULL,
873
+ [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
874
+ [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
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,
880
+};
881
+
882
+#undef COPY_PIXEL
883
+#undef SKIP_PIXEL
884
+
885
+#ifdef SWAP_WORDS
886
+# undef SWAP_WORDS
887
+#endif
888
889
/* Route internal interrupt lines to the global IC */
890
static void pxa2xx_lcdc_int_update(PXA2xxLCDState *s)
40
--
891
--
41
2.20.1
892
2.20.1
42
893
43
894
diff view generated by jsdifflib