1
First pullreq for 6.0: mostly my v8.1M work, plus some other
1
The following changes since commit eae587e8e3694b1aceab23239493fb4c7e1a80f5:
2
bits and pieces. (I still have a lot of stuff in my to-review
3
folder, which I may or may not get to before the Christmas break...)
4
2
5
thanks
3
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-09-13' into staging (2021-09-13 11:00:30 +0100)
6
-- PMM
7
8
The following changes since commit 5e7b204dbfae9a562fc73684986f936b97f63877:
9
10
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2020-12-09 20:08:54 +0000)
11
4
12
are available in the Git repository at:
5
are available in the Git repository at:
13
6
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201210
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210913
15
8
16
for you to fetch changes up to 71f916be1c7e9ede0e37d9cabc781b5a9e8638ff:
9
for you to fetch changes up to 9a2b2ecf4d25a3943918c95d2db4508b304161b5:
17
10
18
hw/arm/armv7m: Correct typo in QOM object name (2020-12-10 11:44:56 +0000)
11
hw/arm/mps2.c: Mark internal-only I2C buses as 'full' (2021-09-13 17:09:28 +0100)
19
12
20
----------------------------------------------------------------
13
----------------------------------------------------------------
21
target-arm queue:
14
target-arm queue:
22
* hw/arm/smmuv3: Fix up L1STD_SPAN decoding
15
* mark MPS2/MPS3 board-internal i2c buses as 'full' so that command
23
* xlnx-zynqmp: Support Xilinx ZynqMP CAN controllers
16
line user-created devices are not plugged into them
24
* sbsa-ref: allow to use Cortex-A53/57/72 cpus
17
* Take an exception if PSTATE.IL is set
25
* Various minor code cleanups
18
* Support an emulated ITS in the virt board
26
* hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
19
* Add support for kudo-bmc board
27
* Implement more pieces of ARMv8.1M support
20
* Probe for KVM_CAP_ARM_VM_IPA_SIZE when creating scratch VM
21
* cadence_uart: Fix clock handling issues that prevented
22
u-boot from running
28
23
29
----------------------------------------------------------------
24
----------------------------------------------------------------
30
Alex Chen (4):
25
Bin Meng (6):
31
i.MX25: Fix bad printf format specifiers
26
hw/misc: zynq_slcr: Correctly compute output clocks in the reset exit phase
32
i.MX31: Fix bad printf format specifiers
27
hw/char: cadence_uart: Disable transmit when input clock is disabled
33
i.MX6: Fix bad printf format specifiers
28
hw/char: cadence_uart: Move clock/reset check to uart_can_receive()
34
i.MX6ul: Fix bad printf format specifiers
29
hw/char: cadence_uart: Convert to memop_with_attrs() ops
30
hw/char: cadence_uart: Ignore access when unclocked or in reset for uart_{read, write}()
31
hw/char: cadence_uart: Log a guest error when device is unclocked or in reset
35
32
36
Havard Skinnemoen (1):
33
Chris Rauer (1):
37
tests/qtest/npcm7xx_rng-test: dump random data on failure
34
hw/arm: Add support for kudo-bmc board.
38
35
39
Kunkun Jiang (1):
36
Marc Zyngier (1):
40
hw/arm/smmuv3: Fix up L1STD_SPAN decoding
37
hw/arm/virt: KVM: Probe for KVM_CAP_ARM_VM_IPA_SIZE when creating scratch VM
41
38
42
Marcin Juszkiewicz (1):
39
Peter Maydell (5):
43
sbsa-ref: allow to use Cortex-A53/57/72 cpus
40
target/arm: Take an exception if PSTATE.IL is set
41
qdev: Support marking individual buses as 'full'
42
hw/arm/mps2-tz.c: Add extra data parameter to MakeDevFn
43
hw/arm/mps2-tz.c: Mark internal-only I2C buses as 'full'
44
hw/arm/mps2.c: Mark internal-only I2C buses as 'full'
44
45
45
Peter Maydell (25):
46
Richard Henderson (1):
46
hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
47
target/arm: Merge disas_a64_insn into aarch64_tr_translate_insn
47
target/arm: Implement v8.1M PXN extension
48
target/arm: Don't clobber ID_PFR1.Security on M-profile cores
49
target/arm: Implement VSCCLRM insn
50
target/arm: Implement CLRM instruction
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
48
72
Vikram Garhwal (4):
49
Shashi Mallela (9):
73
hw/net/can: Introduce Xilinx ZynqMP CAN controller
50
hw/intc: GICv3 ITS initial framework
74
xlnx-zynqmp: Connect Xilinx ZynqMP CAN controllers
51
hw/intc: GICv3 ITS register definitions added
75
tests/qtest: Introduce tests for Xilinx ZynqMP CAN controller
52
hw/intc: GICv3 ITS command queue framework
76
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller
53
hw/intc: GICv3 ITS Command processing
54
hw/intc: GICv3 ITS Feature enablement
55
hw/intc: GICv3 redistributor ITS processing
56
tests/data/acpi/virt: Add IORT files for ITS
57
hw/arm/virt: add ITS support in virt GIC
58
tests/data/acpi/virt: Update IORT files for ITS
77
59
78
meson.build | 1 +
60
docs/system/arm/nuvoton.rst | 1 +
79
hw/arm/smmuv3-internal.h | 2 +-
61
hw/intc/gicv3_internal.h | 188 ++++-
80
hw/net/can/trace.h | 1 +
62
include/hw/arm/virt.h | 2 +
81
include/hw/arm/xlnx-zynqmp.h | 8 +
63
include/hw/intc/arm_gicv3_common.h | 13 +
82
include/hw/intc/armv7m_nvic.h | 2 +
64
include/hw/intc/arm_gicv3_its_common.h | 32 +-
83
include/hw/net/xlnx-zynqmp-can.h | 78 +++
65
include/hw/qdev-core.h | 24 +
84
target/arm/cpu.h | 46 ++
66
target/arm/cpu.h | 1 +
85
target/arm/m-nocp.decode | 10 +-
67
target/arm/kvm_arm.h | 4 +-
86
target/arm/t32.decode | 10 +-
68
target/arm/syndrome.h | 5 +
87
target/arm/vfp.decode | 14 +
69
target/arm/translate.h | 2 +
88
hw/arm/armv7m.c | 4 +-
70
hw/arm/mps2-tz.c | 92 ++-
89
hw/arm/sbsa-ref.c | 23 +-
71
hw/arm/mps2.c | 12 +-
90
hw/arm/xlnx-zcu102.c | 20 +
72
hw/arm/npcm7xx_boards.c | 34 +
91
hw/arm/xlnx-zynqmp.c | 34 ++
73
hw/arm/virt.c | 29 +-
92
hw/intc/armv7m_nvic.c | 246 ++++++--
74
hw/char/cadence_uart.c | 61 +-
93
hw/misc/imx25_ccm.c | 12 +-
75
hw/intc/arm_gicv3.c | 14 +
94
hw/misc/imx31_ccm.c | 14 +-
76
hw/intc/arm_gicv3_common.c | 13 +
95
hw/misc/imx6_ccm.c | 20 +-
77
hw/intc/arm_gicv3_cpuif.c | 7 +-
96
hw/misc/imx6_src.c | 2 +-
78
hw/intc/arm_gicv3_dist.c | 5 +-
97
hw/misc/imx6ul_ccm.c | 4 +-
79
hw/intc/arm_gicv3_its.c | 1322 ++++++++++++++++++++++++++++++++
98
hw/misc/imx_ccm.c | 4 +-
80
hw/intc/arm_gicv3_its_common.c | 7 +-
99
hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++++++++++
81
hw/intc/arm_gicv3_its_kvm.c | 2 +-
100
target/arm/cpu.c | 5 +-
82
hw/intc/arm_gicv3_redist.c | 153 +++-
101
target/arm/helper.c | 7 +-
83
hw/misc/zynq_slcr.c | 31 +-
102
target/arm/m_helper.c | 130 ++++-
84
softmmu/qdev-monitor.c | 7 +-
103
target/arm/translate.c | 105 +++-
85
target/arm/helper-a64.c | 1 +
104
tests/qtest/npcm7xx_rng-test.c | 12 +
86
target/arm/helper.c | 8 +
105
tests/qtest/xlnx-can-test.c | 360 ++++++++++++
87
target/arm/kvm.c | 7 +-
106
MAINTAINERS | 8 +
88
target/arm/translate-a64.c | 255 +++---
107
hw/Kconfig | 1 +
89
target/arm/translate.c | 21 +
108
hw/net/can/meson.build | 1 +
90
hw/intc/meson.build | 1 +
109
hw/net/can/trace-events | 9 +
91
tests/data/acpi/virt/IORT | Bin 0 -> 124 bytes
110
target/arm/translate-vfp.c.inc | 511 ++++++++++++++++-
92
tests/data/acpi/virt/IORT.memhp | Bin 0 -> 124 bytes
111
tests/qtest/meson.build | 1 +
93
tests/data/acpi/virt/IORT.numamem | Bin 0 -> 124 bytes
112
34 files changed, 2713 insertions(+), 153 deletions(-)
94
tests/data/acpi/virt/IORT.pxb | Bin 0 -> 124 bytes
113
create mode 100644 hw/net/can/trace.h
95
35 files changed, 2144 insertions(+), 210 deletions(-)
114
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
96
create mode 100644 hw/intc/arm_gicv3_its.c
115
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
97
create mode 100644 tests/data/acpi/virt/IORT
116
create mode 100644 tests/qtest/xlnx-can-test.c
98
create mode 100644 tests/data/acpi/virt/IORT.memhp
117
create mode 100644 hw/net/can/trace-events
99
create mode 100644 tests/data/acpi/virt/IORT.numamem
100
create mode 100644 tests/data/acpi/virt/IORT.pxb
118
101
diff view generated by jsdifflib
Deleted patch
1
From: Kunkun Jiang <jiangkunkun@huawei.com>
2
1
3
Accroding to the SMMUv3 spec, the SPAN field of Level1 Stream Table
4
Descriptor is 5 bits([4:0]).
5
6
Fixes: 9bde7f0674f(hw/arm/smmuv3: Implement translate callback)
7
Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com>
8
Message-id: 20201124023711.1184-1-jiangkunkun@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Acked-by: Eric Auger <eric.auger@redhat.com>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/arm/smmuv3-internal.h | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/smmuv3-internal.h
19
+++ b/hw/arm/smmuv3-internal.h
20
@@ -XXX,XX +XXX,XX @@ static inline uint64_t l1std_l2ptr(STEDesc *desc)
21
return hi << 32 | lo;
22
}
23
24
-#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 4))
25
+#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 5))
26
27
#endif
28
--
29
2.20.1
30
31
diff view generated by jsdifflib
1
For M-profile CPUs, the range from 0xe0000000 to 0xe00fffff is the
1
From: Bin Meng <bmeng.cn@gmail.com>
2
Private Peripheral Bus range, which includes all of the memory mapped
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
2
10
The architecture is clear that within the SCS unimplemented registers
3
As of today, when booting upstream U-Boot for Xilinx Zynq, the UART
11
should be RES0 for privileged accesses and generate BusFault for
4
does not receive anything. Debugging shows that the UART input clock
12
unprivileged accesses, and we currently implement this.
5
frequency is zero which prevents the UART from receiving anything as
6
per the logic in uart_receive().
13
7
14
It is less clear about how to handle accesses to unimplemented
8
From zynq_slcr_reset_exit() comment, it intends to compute output
15
regions of the wider PPB. Unprivileged accesses should definitely
9
clocks according to ps_clk and registers. zynq_slcr_compute_clocks()
16
cause BusFaults (R_DQQS), but the behaviour of privileged accesses is
10
is called to accomplish the task, inside which device_is_in_reset()
17
not given as a general rule. However, the register definitions of
11
is called to actually make the attempt in vain.
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
12
24
Expand the container MemoryRegion that the NVIC exposes so that
13
Rework reset_hold() and reset_exit() so that in the reset exit phase,
25
it covers the whole PPB space. This means:
14
the logic can really compute output clocks in reset_exit().
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
15
16
With this change, upstream U-Boot boots properly again with:
17
18
$ qemu-system-arm -M xilinx-zynq-a9 -m 1G -display none -serial null -serial stdio \
19
-device loader,file=u-boot-dtb.bin,addr=0x4000000,cpu-num=0
20
21
Fixes: 38867cb7ec90 ("hw/misc/zynq_slcr: add clock generation for uarts")
22
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
23
Acked-by: Alistair Francis <alistair.francis@wdc.com>
24
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
25
Message-id: 20210901124521.30599-2-bmeng.cn@gmail.com
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
35
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
36
Message-id: 20201119215617.29887-2-peter.maydell@linaro.org
37
---
27
---
38
include/hw/intc/armv7m_nvic.h | 1 +
28
hw/misc/zynq_slcr.c | 31 ++++++++++++++++++-------------
39
hw/arm/armv7m.c | 2 +-
29
1 file changed, 18 insertions(+), 13 deletions(-)
40
hw/intc/armv7m_nvic.c | 78 ++++++++++++++++++++++++++++++-----
41
3 files changed, 69 insertions(+), 12 deletions(-)
42
30
43
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
31
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
44
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
45
--- a/include/hw/intc/armv7m_nvic.h
33
--- a/hw/misc/zynq_slcr.c
46
+++ b/include/hw/intc/armv7m_nvic.h
34
+++ b/hw/misc/zynq_slcr.c
47
@@ -XXX,XX +XXX,XX @@ struct NVICState {
35
@@ -XXX,XX +XXX,XX @@ static uint64_t zynq_slcr_compute_clock(const uint64_t periods[],
48
MemoryRegion systickmem;
36
zynq_slcr_compute_clock((plls), (state)->regs[reg], \
49
MemoryRegion systick_ns_mem;
37
reg ## _ ## enable_field ## _SHIFT)
50
MemoryRegion container;
38
51
+ MemoryRegion defaultmem;
39
+static void zynq_slcr_compute_clocks_internal(ZynqSLCRState *s, uint64_t ps_clk)
52
53
uint32_t num_irq;
54
qemu_irq excpout;
55
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/arm/armv7m.c
58
+++ b/hw/arm/armv7m.c
59
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
60
sysbus_connect_irq(sbd, 0,
61
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
62
63
- memory_region_add_subregion(&s->container, 0xe000e000,
64
+ memory_region_add_subregion(&s->container, 0xe0000000,
65
sysbus_mmio_get_region(sbd, 0));
66
67
for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
68
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/intc/armv7m_nvic.c
71
+++ b/hw/intc/armv7m_nvic.c
72
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
73
.endianness = DEVICE_NATIVE_ENDIAN,
74
};
75
76
+/*
77
+ * Unassigned portions of the PPB space are RAZ/WI for privileged
78
+ * accesses, and fault for non-privileged accesses.
79
+ */
80
+static MemTxResult ppb_default_read(void *opaque, hwaddr addr,
81
+ uint64_t *data, unsigned size,
82
+ MemTxAttrs attrs)
83
+{
40
+{
84
+ qemu_log_mask(LOG_UNIMP, "Read of unassigned area of PPB: offset 0x%x\n",
41
+ uint64_t io_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_IO_PLL_CTRL]);
85
+ (uint32_t)addr);
42
+ uint64_t arm_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_ARM_PLL_CTRL]);
86
+ if (attrs.user) {
43
+ uint64_t ddr_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_DDR_PLL_CTRL]);
87
+ return MEMTX_ERROR;
44
+
88
+ }
45
+ uint64_t uart_mux[4] = {io_pll, io_pll, arm_pll, ddr_pll};
89
+ *data = 0;
46
+
90
+ return MEMTX_OK;
47
+ /* compute uartX reference clocks */
48
+ clock_set(s->uart0_ref_clk,
49
+ ZYNQ_COMPUTE_CLK(s, uart_mux, R_UART_CLK_CTRL, CLKACT0));
50
+ clock_set(s->uart1_ref_clk,
51
+ ZYNQ_COMPUTE_CLK(s, uart_mux, R_UART_CLK_CTRL, CLKACT1));
91
+}
52
+}
92
+
53
+
93
+static MemTxResult ppb_default_write(void *opaque, hwaddr addr,
54
/**
94
+ uint64_t value, unsigned size,
55
* Compute and set the ouputs clocks periods.
95
+ MemTxAttrs attrs)
56
* But do not propagate them further. Connected clocks
96
+{
57
@@ -XXX,XX +XXX,XX @@ static void zynq_slcr_compute_clocks(ZynqSLCRState *s)
97
+ qemu_log_mask(LOG_UNIMP, "Write of unassigned area of PPB: offset 0x%x\n",
58
ps_clk = 0;
98
+ (uint32_t)addr);
99
+ if (attrs.user) {
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
}
59
}
127
60
128
- /* The NVIC and System Control Space (SCS) starts at 0xe000e000
61
- uint64_t io_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_IO_PLL_CTRL]);
129
+ /*
62
- uint64_t arm_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_ARM_PLL_CTRL]);
130
+ * This device provides a single sysbus memory region which
63
- uint64_t ddr_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_DDR_PLL_CTRL]);
131
+ * represents the whole of the "System PPB" space. This is the
64
-
132
+ * range from 0xe0000000 to 0xe00fffff and includes the NVIC,
65
- uint64_t uart_mux[4] = {io_pll, io_pll, arm_pll, ddr_pll};
133
+ * the System Control Space (system registers), the systick timer,
66
-
134
+ * and for CPUs with the Security extension an NS banked version
67
- /* compute uartX reference clocks */
135
+ * of all of these.
68
- clock_set(s->uart0_ref_clk,
136
+ *
69
- ZYNQ_COMPUTE_CLK(s, uart_mux, R_UART_CLK_CTRL, CLKACT0));
137
+ * The default behaviour for unimplemented registers/ranges
70
- clock_set(s->uart1_ref_clk,
138
+ * (for instance the Data Watchpoint and Trace unit at 0xe0001000)
71
- ZYNQ_COMPUTE_CLK(s, uart_mux, R_UART_CLK_CTRL, CLKACT1));
139
+ * is to RAZ/WI for privileged access and BusFault for non-privileged
72
+ zynq_slcr_compute_clocks_internal(s, ps_clk);
140
+ * access.
73
}
141
+ *
74
142
+ * The NVIC and System Control Space (SCS) starts at 0xe000e000
75
/**
143
* and looks like this:
76
@@ -XXX,XX +XXX,XX @@ static void zynq_slcr_reset_hold(Object *obj)
144
* 0x004 - ICTR
77
ZynqSLCRState *s = ZYNQ_SLCR(obj);
145
* 0x010 - 0xff - systick
78
146
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
79
/* will disable all output clocks */
147
* generally code determining which banked register to use should
80
- zynq_slcr_compute_clocks(s);
148
* use attrs.secure; code determining actual behaviour of the system
81
+ zynq_slcr_compute_clocks_internal(s, 0);
149
* should use env->v7m.secure.
82
zynq_slcr_propagate_clocks(s);
150
+ *
83
}
151
+ * The container covers the whole PPB space. Within it the priority
84
152
+ * of overlapping regions is:
85
@@ -XXX,XX +XXX,XX @@ static void zynq_slcr_reset_exit(Object *obj)
153
+ * - default region (for RAZ/WI and BusFault) : -1
86
ZynqSLCRState *s = ZYNQ_SLCR(obj);
154
+ * - system register regions : 0
87
155
+ * - systick : 1
88
/* will compute output clocks according to ps_clk and registers */
156
+ * This is because the systick device is a small block of registers
89
- zynq_slcr_compute_clocks(s);
157
+ * in the middle of the other system control registers.
90
+ zynq_slcr_compute_clocks_internal(s, clock_get(s->ps_clk));
158
*/
91
zynq_slcr_propagate_clocks(s);
159
- regionlen = arm_feature(&s->cpu->env, ARM_FEATURE_V8) ? 0x21000 : 0x1000;
92
}
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
93
195
--
94
--
196
2.20.1
95
2.20.1
197
96
198
97
diff view generated by jsdifflib
1
v8.1M adds new encodings of VLLDM and VLSTM (where bit 7 is set).
1
From: Bin Meng <bmeng.cn@gmail.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
At present when input clock is disabled, any character transmitted
10
instructions behave identically assuming they don't UNDEF.
4
to tx fifo can still show on the serial line, which is wrong.
11
5
6
Fixes: b636db306e06 ("hw/char/cadence_uart: add clock support")
7
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Message-id: 20210901124521.30599-3-bmeng.cn@gmail.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
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
---
12
---
16
target/arm/m-nocp.decode | 2 +-
13
hw/char/cadence_uart.c | 5 +++++
17
target/arm/translate-vfp.c.inc | 25 +++++++++++++++++++++++++
14
1 file changed, 5 insertions(+)
18
2 files changed, 26 insertions(+), 1 deletion(-)
19
15
20
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
16
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
21
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/m-nocp.decode
18
--- a/hw/char/cadence_uart.c
23
+++ b/target/arm/m-nocp.decode
19
+++ b/hw/char/cadence_uart.c
24
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static gboolean cadence_uart_xmit(void *do_not_use, GIOCondition cond,
25
21
static void uart_write_tx_fifo(CadenceUARTState *s, const uint8_t *buf,
22
int size)
26
{
23
{
27
# Special cases which do not take an early NOCP: VLLDM and VLSTM
24
+ /* ignore characters when unclocked or in reset */
28
- VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
25
+ if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
29
+ VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 op:1 000 0000
26
+ return;
30
# VSCCLRM (new in v8.1M) is similar:
31
VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
32
VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
33
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/translate-vfp.c.inc
36
+++ b/target/arm/translate-vfp.c.inc
37
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
38
!arm_dc_feature(s, ARM_FEATURE_V8)) {
39
return false;
40
}
41
+
42
+ if (a->op) {
43
+ /*
44
+ * T2 encoding ({D0-D31} reglist): v8.1M and up. We choose not
45
+ * to take the IMPDEF option to make memory accesses to the stack
46
+ * slots that correspond to the D16-D31 registers (discarding
47
+ * read data and writing UNKNOWN values), so for us the T2
48
+ * encoding behaves identically to the T1 encoding.
49
+ */
50
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
51
+ return false;
52
+ }
53
+ } else {
54
+ /*
55
+ * T1 encoding ({D0-D15} reglist); undef if we have 32 Dregs.
56
+ * This is currently architecturally impossible, but we add the
57
+ * check to stay in line with the pseudocode. Note that we must
58
+ * emit code for the UNDEF so it takes precedence over the NOCP.
59
+ */
60
+ if (dc_isar_feature(aa32_simd_r32, s)) {
61
+ unallocated_encoding(s);
62
+ return true;
63
+ }
64
+ }
27
+ }
65
+
28
+
66
/*
29
if ((s->r[R_CR] & UART_CR_TX_DIS) || !(s->r[R_CR] & UART_CR_TX_EN)) {
67
* If not secure, UNDEF. We must emit code for this
30
return;
68
* rather than returning false so that this takes
31
}
69
--
32
--
70
2.20.1
33
2.20.1
71
34
72
35
diff view generated by jsdifflib
1
In commit 077d7449100d824a4 we added code to handle the v8M
1
From: Bin Meng <bmeng.cn@gmail.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
Currently the clock/reset check is done in uart_receive(), but we
14
security state" we detected the illegal-return case but went ahead
4
can move the check to uart_can_receive() which is earlier.
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
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
19
cases, then see if we really need to deactivate NMI or HardFault
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
20
instead, and finally do the deactivation.
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 20210901124521.30599-4-bmeng.cn@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/char/cadence_uart.c | 17 ++++++++++-------
13
1 file changed, 10 insertions(+), 7 deletions(-)
21
14
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
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
16
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/intc/armv7m_nvic.c
17
--- a/hw/char/cadence_uart.c
32
+++ b/hw/intc/armv7m_nvic.c
18
+++ b/hw/char/cadence_uart.c
33
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
19
@@ -XXX,XX +XXX,XX @@ static void uart_parameters_setup(CadenceUARTState *s)
20
static int uart_can_receive(void *opaque)
34
{
21
{
35
NVICState *s = (NVICState *)opaque;
22
CadenceUARTState *s = opaque;
36
VecInfo *vec = NULL;
23
- int ret = MAX(CADENCE_UART_RX_FIFO_SIZE, CADENCE_UART_TX_FIFO_SIZE);
37
- int ret;
24
- uint32_t ch_mode = s->r[R_MR] & UART_MR_CHMODE;
38
+ int ret = 0;
25
+ int ret;
39
26
+ uint32_t ch_mode;
40
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
41
42
+ trace_nvic_complete_irq(irq, secure);
43
+
27
+
44
+ if (secure && exc_is_banked(irq)) {
28
+ /* ignore characters when unclocked or in reset */
45
+ vec = &s->sec_vectors[irq];
29
+ if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
46
+ } else {
30
+ return 0;
47
+ vec = &s->vectors[irq];
48
+ }
31
+ }
49
+
32
+
50
+ /*
33
+ ret = MAX(CADENCE_UART_RX_FIFO_SIZE, CADENCE_UART_TX_FIFO_SIZE);
51
+ * Identify illegal exception return cases. We can't immediately
34
+ ch_mode = s->r[R_MR] & UART_MR_CHMODE;
52
+ * return at this point because we still need to deactivate
35
53
+ * (either this exception or NMI/HardFault) first.
36
if (ch_mode == NORMAL_MODE || ch_mode == ECHO_MODE) {
54
+ */
37
ret = MIN(ret, CADENCE_UART_RX_FIFO_SIZE - s->rx_count);
55
+ if (!exc_is_banked(irq) && exc_targets_secure(s, irq) != secure) {
38
@@ -XXX,XX +XXX,XX @@ static void uart_receive(void *opaque, const uint8_t *buf, int size)
56
+ /*
39
CadenceUARTState *s = opaque;
57
+ * Return from a configurable exception targeting the opposite
40
uint32_t ch_mode = s->r[R_MR] & UART_MR_CHMODE;
58
+ * security state from the one we're trying to complete it for.
41
59
+ * Clear vec because it's not really the VecInfo for this
42
- /* ignore characters when unclocked or in reset */
60
+ * (irq, secstate) so we mustn't deactivate it.
43
- if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
61
+ */
44
- return;
62
+ ret = -1;
63
+ vec = NULL;
64
+ } else if (!vec->active) {
65
+ /* Return from an inactive interrupt */
66
+ ret = -1;
67
+ } else {
68
+ /* Legal return, we will return the RETTOBASE bit value to the caller */
69
+ ret = nvic_rettobase(s);
70
+ }
71
+
72
/*
73
* For negative priorities, v8M will forcibly deactivate the appropriate
74
* NMI or HardFault regardless of what interrupt we're being asked to
75
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
76
}
77
78
if (!vec) {
79
- if (secure && exc_is_banked(irq)) {
80
- vec = &s->sec_vectors[irq];
81
- } else {
82
- vec = &s->vectors[irq];
83
- }
84
- }
45
- }
85
-
46
-
86
- trace_nvic_complete_irq(irq, secure);
47
if (ch_mode == NORMAL_MODE || ch_mode == ECHO_MODE) {
87
-
48
uart_write_rx_fifo(opaque, buf, size);
88
- if (!vec->active) {
89
- /* Tell the caller this was an illegal exception return */
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
}
49
}
107
108
vec->active = 0;
109
--
50
--
110
2.20.1
51
2.20.1
111
52
112
53
diff view generated by jsdifflib
1
For v8.1M the architecture mandates that CPUs must provide at
1
From: Bin Meng <bmeng.cn@gmail.com>
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
This converts uart_read() and uart_write() to memop_with_attrs() ops.
4
5
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 20210901124521.30599-5-bmeng.cn@gmail.com
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
hw/char/cadence_uart.c | 26 +++++++++++++++-----------
21
target/arm/t32.decode | 4 ++++
12
1 file changed, 15 insertions(+), 11 deletions(-)
22
hw/intc/armv7m_nvic.c | 13 +++++++++++++
23
3 files changed, 31 insertions(+)
24
13
25
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
26
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/cpu.h
16
--- a/hw/char/cadence_uart.c
28
+++ b/target/arm/cpu.h
17
+++ b/hw/char/cadence_uart.c
29
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, LSM, 20, 4)
18
@@ -XXX,XX +XXX,XX @@ static void uart_read_rx_fifo(CadenceUARTState *s, uint32_t *c)
30
FIELD(ID_MMFR4, CCIDX, 24, 4)
19
uart_update_status(s);
31
FIELD(ID_MMFR4, EVT, 28, 4)
32
33
+FIELD(ID_PFR0, STATE0, 0, 4)
34
+FIELD(ID_PFR0, STATE1, 4, 4)
35
+FIELD(ID_PFR0, STATE2, 8, 4)
36
+FIELD(ID_PFR0, STATE3, 12, 4)
37
+FIELD(ID_PFR0, CSV2, 16, 4)
38
+FIELD(ID_PFR0, AMU, 20, 4)
39
+FIELD(ID_PFR0, DIT, 24, 4)
40
+FIELD(ID_PFR0, RAS, 28, 4)
41
+
42
FIELD(ID_PFR1, PROGMOD, 0, 4)
43
FIELD(ID_PFR1, SECURITY, 4, 4)
44
FIELD(ID_PFR1, MPROGMOD, 8, 4)
45
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
46
return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0;
47
}
20
}
48
21
49
+static inline bool isar_feature_aa32_ras(const ARMISARegisters *id)
22
-static void uart_write(void *opaque, hwaddr offset,
50
+{
23
- uint64_t value, unsigned size)
51
+ return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0;
24
+static MemTxResult uart_write(void *opaque, hwaddr offset,
52
+}
25
+ uint64_t value, unsigned size, MemTxAttrs attrs)
53
+
54
static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
55
{
26
{
56
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
27
CadenceUARTState *s = opaque;
57
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
28
58
index XXXXXXX..XXXXXXX 100644
29
DB_PRINT(" offset:%x data:%08x\n", (unsigned)offset, (unsigned)value);
59
--- a/target/arm/t32.decode
30
offset >>= 2;
60
+++ b/target/arm/t32.decode
31
if (offset >= CADENCE_UART_R_MAX) {
61
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
32
- return;
62
# SEV 1111 0011 1010 1111 1000 0000 0000 0100
33
+ return MEMTX_DECODE_ERROR;
63
# SEVL 1111 0011 1010 1111 1000 0000 0000 0101
34
}
64
35
switch (offset) {
65
+ # For M-profile minimal-RAS ESB can be a NOP, which is the
36
case R_IER: /* ier (wts imr) */
66
+ # default behaviour since it is in the hint space.
37
@@ -XXX,XX +XXX,XX @@ static void uart_write(void *opaque, hwaddr offset,
67
+ # ESB 1111 0011 1010 1111 1000 0000 0001 0000
68
+
69
# The canonical nop ends in 0000 0000, but the whole rest
70
# of the space is "reserved hint, behaves as nop".
71
NOP 1111 0011 1010 1111 1000 0000 ---- ----
72
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/hw/intc/armv7m_nvic.c
75
+++ b/hw/intc/armv7m_nvic.c
76
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
77
return 0;
78
}
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;
38
break;
100
}
39
}
101
+ case 0xf04: /* RFSR */
40
uart_update_status(s);
102
+ if (!cpu_isar_feature(aa32_ras, cpu)) {
41
+
103
+ goto bad_offset;
42
+ return MEMTX_OK;
104
+ }
43
}
105
+ /* We provide minimal-RAS only: RFSR is RAZ/WI */
44
106
+ break;
45
-static uint64_t uart_read(void *opaque, hwaddr offset,
107
case 0xf34: /* FPCCR */
46
- unsigned size)
108
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
47
+static MemTxResult uart_read(void *opaque, hwaddr offset,
109
/* Not all bits here are banked. */
48
+ uint64_t *value, unsigned size, MemTxAttrs attrs)
49
{
50
CadenceUARTState *s = opaque;
51
uint32_t c = 0;
52
53
offset >>= 2;
54
if (offset >= CADENCE_UART_R_MAX) {
55
- c = 0;
56
- } else if (offset == R_TX_RX) {
57
+ return MEMTX_DECODE_ERROR;
58
+ }
59
+ if (offset == R_TX_RX) {
60
uart_read_rx_fifo(s, &c);
61
} else {
62
- c = s->r[offset];
63
+ c = s->r[offset];
64
}
65
66
DB_PRINT(" offset:%x data:%08x\n", (unsigned)(offset << 2), (unsigned)c);
67
- return c;
68
+ *value = c;
69
+ return MEMTX_OK;
70
}
71
72
static const MemoryRegionOps uart_ops = {
73
- .read = uart_read,
74
- .write = uart_write,
75
+ .read_with_attrs = uart_read,
76
+ .write_with_attrs = uart_write,
77
.endianness = DEVICE_NATIVE_ENDIAN,
78
};
79
110
--
80
--
111
2.20.1
81
2.20.1
112
82
113
83
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Bin Meng <bmeng.cn@gmail.com>
2
2
3
Connect CAN0 and CAN1 on the ZynqMP.
3
Read or write to uart registers when unclocked or in reset should be
4
ignored. Add the check there, and as a result of this, the check in
5
uart_write_tx_fifo() is now unnecessary.
4
6
5
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
7
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 1605728926-352690-3-git-send-email-fnu.vikram@xilinx.com
10
Message-id: 20210901124521.30599-6-bmeng.cn@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
12
---
11
include/hw/arm/xlnx-zynqmp.h | 8 ++++++++
13
hw/char/cadence_uart.c | 15 ++++++++++-----
12
hw/arm/xlnx-zcu102.c | 20 ++++++++++++++++++++
14
1 file changed, 10 insertions(+), 5 deletions(-)
13
hw/arm/xlnx-zynqmp.c | 34 ++++++++++++++++++++++++++++++++++
14
3 files changed, 62 insertions(+)
15
15
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
16
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-zynqmp.h
18
--- a/hw/char/cadence_uart.c
19
+++ b/include/hw/arm/xlnx-zynqmp.h
19
+++ b/hw/char/cadence_uart.c
20
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static gboolean cadence_uart_xmit(void *do_not_use, GIOCondition cond,
21
#include "hw/intc/arm_gic.h"
21
static void uart_write_tx_fifo(CadenceUARTState *s, const uint8_t *buf,
22
#include "hw/net/cadence_gem.h"
22
int size)
23
#include "hw/char/cadence_uart.h"
23
{
24
+#include "hw/net/xlnx-zynqmp-can.h"
24
- /* ignore characters when unclocked or in reset */
25
#include "hw/ide/ahci.h"
25
- if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
26
#include "hw/sd/sdhci.h"
26
- return;
27
#include "hw/ssi/xilinx_spips.h"
27
- }
28
@@ -XXX,XX +XXX,XX @@
28
-
29
#include "hw/cpu/cluster.h"
29
if ((s->r[R_CR] & UART_CR_TX_DIS) || !(s->r[R_CR] & UART_CR_TX_EN)) {
30
#include "target/arm/cpu.h"
30
return;
31
#include "qom/object.h"
31
}
32
+#include "net/can_emu.h"
32
@@ -XXX,XX +XXX,XX @@ static MemTxResult uart_write(void *opaque, hwaddr offset,
33
33
{
34
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
34
CadenceUARTState *s = opaque;
35
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
35
36
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
36
+ /* ignore access when unclocked or in reset */
37
#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
37
+ if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
38
#define XLNX_ZYNQMP_NUM_GEMS 4
38
+ return MEMTX_ERROR;
39
#define XLNX_ZYNQMP_NUM_UARTS 2
40
+#define XLNX_ZYNQMP_NUM_CAN 2
41
+#define XLNX_ZYNQMP_CAN_REF_CLK (24 * 1000 * 1000)
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
+ }
39
+ }
95
+
40
+
96
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
41
DB_PRINT(" offset:%x data:%08x\n", (unsigned)offset, (unsigned)value);
97
42
offset >>= 2;
98
/* Create and plug in the SD cards */
43
if (offset >= CADENCE_UART_R_MAX) {
99
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
44
@@ -XXX,XX +XXX,XX @@ static MemTxResult uart_read(void *opaque, hwaddr offset,
100
s->secure = false;
45
CadenceUARTState *s = opaque;
101
/* Default to virt (EL2) being disabled */
46
uint32_t c = 0;
102
s->virt = false;
47
103
+ object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
48
+ /* ignore access when unclocked or in reset */
104
+ (Object **)&s->canbus[0],
49
+ if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
105
+ object_property_allow_set_link,
50
+ return MEMTX_ERROR;
106
+ 0);
107
+
108
+ object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
109
+ (Object **)&s->canbus[1],
110
+ object_property_allow_set_link,
111
+ 0);
112
}
113
114
static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
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
+ }
51
+ }
142
+
52
+
143
object_initialize_child(obj, "sata", &s->sata, TYPE_SYSBUS_AHCI);
53
offset >>= 2;
144
54
if (offset >= CADENCE_UART_R_MAX) {
145
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
55
return MEMTX_DECODE_ERROR;
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
--
56
--
182
2.20.1
57
2.20.1
183
58
184
59
diff view generated by jsdifflib
1
From: Alex Chen <alex.chen@huawei.com>
1
From: Bin Meng <bmeng.cn@gmail.com>
2
2
3
We should use printf format specifier "%u" instead of "%d" for
3
We've got SW that expects FSBL (Bootlooader) to setup clocks and
4
argument of type "unsigned int".
4
resets. It's quite common that users run that SW on QEMU without
5
FSBL (FSBL typically requires the Xilinx tools installed). That's
6
fine, since users can stil use -device loader to enable clocks etc.
5
7
6
Reported-by: Euler Robot <euler.robot@huawei.com>
8
To help folks understand what's going, a log (guest-error) message
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
9
would be helpful here. In particular with the serial port since
8
Message-id: 20201126111109.112238-3-alex.chen@huawei.com
10
things will go very quiet if they get things wrong.
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
12
Suggested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
13
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
14
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
15
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
Message-id: 20210901124521.30599-7-bmeng.cn@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
18
---
12
hw/misc/imx31_ccm.c | 14 +++++++-------
19
hw/char/cadence_uart.c | 8 ++++++++
13
hw/misc/imx_ccm.c | 4 ++--
20
1 file changed, 8 insertions(+)
14
2 files changed, 9 insertions(+), 9 deletions(-)
15
21
16
diff --git a/hw/misc/imx31_ccm.c b/hw/misc/imx31_ccm.c
22
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
17
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/misc/imx31_ccm.c
24
--- a/hw/char/cadence_uart.c
19
+++ b/hw/misc/imx31_ccm.c
25
+++ b/hw/char/cadence_uart.c
20
@@ -XXX,XX +XXX,XX @@ static const char *imx31_ccm_reg_name(uint32_t reg)
26
@@ -XXX,XX +XXX,XX @@ static int uart_can_receive(void *opaque)
21
case IMX31_CCM_PDR2_REG:
27
22
return "PDR2";
28
/* ignore characters when unclocked or in reset */
23
default:
29
if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
24
- sprintf(unknown, "[%d ?]", reg);
30
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: uart is unclocked or in reset\n",
25
+ sprintf(unknown, "[%u ?]", reg);
31
+ __func__);
26
return unknown;
32
return 0;
27
}
33
}
28
}
34
29
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_pll_ref_clk(IMXCCMState *dev)
35
@@ -XXX,XX +XXX,XX @@ static void uart_event(void *opaque, QEMUChrEvent event)
30
freq = CKIH_FREQ;
36
37
/* ignore characters when unclocked or in reset */
38
if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
39
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: uart is unclocked or in reset\n",
40
+ __func__);
41
return;
31
}
42
}
32
43
33
- DPRINTF("freq = %d\n", freq);
44
@@ -XXX,XX +XXX,XX @@ static MemTxResult uart_write(void *opaque, hwaddr offset,
34
+ DPRINTF("freq = %u\n", freq);
45
35
46
/* ignore access when unclocked or in reset */
36
return freq;
47
if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
37
}
48
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: uart is unclocked or in reset\n",
38
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_mpll_clk(IMXCCMState *dev)
49
+ __func__);
39
freq = imx_ccm_calc_pll(s->reg[IMX31_CCM_MPCTL_REG],
50
return MEMTX_ERROR;
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
}
51
}
50
52
51
- DPRINTF("freq = %d\n", freq);
53
@@ -XXX,XX +XXX,XX @@ static MemTxResult uart_read(void *opaque, hwaddr offset,
52
+ DPRINTF("freq = %u\n", freq);
54
53
55
/* ignore access when unclocked or in reset */
54
return freq;
56
if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
55
}
57
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: uart is unclocked or in reset\n",
56
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_hclk_clk(IMXCCMState *dev)
58
+ __func__);
57
freq = imx31_ccm_get_mcu_main_clk(dev)
59
return MEMTX_ERROR;
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
}
60
}
77
61
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
85
--- a/hw/misc/imx_ccm.c
86
+++ b/hw/misc/imx_ccm.c
87
@@ -XXX,XX +XXX,XX @@ uint32_t imx_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
88
freq = klass->get_clock_frequency(dev, clock);
89
}
90
91
- DPRINTF("(clock = %d) = %d\n", clock, freq);
92
+ DPRINTF("(clock = %d) = %u\n", clock, freq);
93
94
return freq;
95
}
96
@@ -XXX,XX +XXX,XX @@ uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq)
97
freq = ((2 * (base_freq >> 10) * (mfi * mfd + mfn)) /
98
(mfd * pd)) << 10;
99
100
- DPRINTF("(pllreg = 0x%08x, base_freq = %d) = %d\n", pllreg, base_freq,
101
+ DPRINTF("(pllreg = 0x%08x, base_freq = %u) = %d\n", pllreg, base_freq,
102
freq);
103
104
return freq;
105
--
62
--
106
2.20.1
63
2.20.1
107
64
108
65
diff view generated by jsdifflib
1
Implement the new-in-v8.1M FPCXT_S floating point system register.
1
From: Marc Zyngier <maz@kernel.org>
2
This is for saving and restoring the secure floating point context,
3
and it reads and writes bits [27:0] from the FPSCR and the
4
CONTROL.SFPA bit in bit [31].
5
2
3
Although we probe for the IPA limits imposed by KVM (and the hardware)
4
when computing the memory map, we still use the old style '0' when
5
creating a scratch VM in kvm_arm_create_scratch_host_vcpu().
6
7
On systems that are severely IPA challenged (such as the Apple M1),
8
this results in a failure as KVM cannot use the default 40bit that
9
'0' represents.
10
11
Instead, probe for the extension and use the reported IPA limit
12
if available.
13
14
Cc: Andrew Jones <drjones@redhat.com>
15
Cc: Eric Auger <eric.auger@redhat.com>
16
Cc: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Marc Zyngier <maz@kernel.org>
18
Reviewed-by: Andrew Jones <drjones@redhat.com>
19
Message-id: 20210822144441.1290891-2-maz@kernel.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-14-peter.maydell@linaro.org
9
---
21
---
10
target/arm/translate-vfp.c.inc | 58 ++++++++++++++++++++++++++++++++++
22
target/arm/kvm.c | 7 ++++++-
11
1 file changed, 58 insertions(+)
23
1 file changed, 6 insertions(+), 1 deletion(-)
12
24
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
25
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
14
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
27
--- a/target/arm/kvm.c
16
+++ b/target/arm/translate-vfp.c.inc
28
+++ b/target/arm/kvm.c
17
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
29
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
18
return false;
30
struct kvm_vcpu_init *init)
19
}
31
{
20
break;
32
int ret = 0, kvmfd = -1, vmfd = -1, cpufd = -1;
21
+ case ARM_VFP_FPCXT_S:
33
+ int max_vm_pa_size;
22
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
34
23
+ return false;
35
kvmfd = qemu_open_old("/dev/kvm", O_RDWR);
24
+ }
36
if (kvmfd < 0) {
25
+ if (!s->v8m_secure) {
37
goto err;
26
+ return false;
27
+ }
28
+ break;
29
default:
30
return FPSysRegCheckFailed;
31
}
38
}
32
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
39
- vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0);
33
tcg_temp_free_i32(tmp);
40
+ max_vm_pa_size = ioctl(kvmfd, KVM_CHECK_EXTENSION, KVM_CAP_ARM_VM_IPA_SIZE);
34
break;
41
+ if (max_vm_pa_size < 0) {
35
}
42
+ max_vm_pa_size = 0;
36
+ case ARM_VFP_FPCXT_S:
37
+ {
38
+ TCGv_i32 sfpa, control, fpscr;
39
+ /* Set FPSCR[27:0] and CONTROL.SFPA from value */
40
+ tmp = loadfn(s, opaque);
41
+ sfpa = tcg_temp_new_i32();
42
+ tcg_gen_shri_i32(sfpa, tmp, 31);
43
+ control = load_cpu_field(v7m.control[M_REG_S]);
44
+ tcg_gen_deposit_i32(control, control, sfpa,
45
+ R_V7M_CONTROL_SFPA_SHIFT, 1);
46
+ store_cpu_field(control, v7m.control[M_REG_S]);
47
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
48
+ tcg_gen_andi_i32(fpscr, fpscr, FPCR_NZCV_MASK);
49
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
50
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
51
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
52
+ tcg_temp_free_i32(tmp);
53
+ tcg_temp_free_i32(sfpa);
54
+ break;
55
+ }
43
+ }
56
default:
44
+ vmfd = ioctl(kvmfd, KVM_CREATE_VM, max_vm_pa_size);
57
g_assert_not_reached();
45
if (vmfd < 0) {
58
}
46
goto err;
59
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
60
tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
61
storefn(s, opaque, tmp);
62
break;
63
+ case ARM_VFP_FPCXT_S:
64
+ {
65
+ TCGv_i32 control, sfpa, fpscr;
66
+ /* Bits [27:0] from FPSCR, bit [31] from CONTROL.SFPA */
67
+ tmp = tcg_temp_new_i32();
68
+ sfpa = tcg_temp_new_i32();
69
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
70
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
71
+ control = load_cpu_field(v7m.control[M_REG_S]);
72
+ tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
73
+ tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
74
+ tcg_gen_or_i32(tmp, tmp, sfpa);
75
+ tcg_temp_free_i32(sfpa);
76
+ /*
77
+ * Store result before updating FPSCR etc, in case
78
+ * it is a memory write which causes an exception.
79
+ */
80
+ storefn(s, opaque, tmp);
81
+ /*
82
+ * Now we must reset FPSCR from FPDSCR_NS, and clear
83
+ * CONTROL.SFPA; so we'll end the TB here.
84
+ */
85
+ tcg_gen_andi_i32(control, control, ~R_V7M_CONTROL_SFPA_MASK);
86
+ store_cpu_field(control, v7m.control[M_REG_S]);
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
}
47
}
96
--
48
--
97
2.20.1
49
2.20.1
98
50
99
51
diff view generated by jsdifflib
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
1
From: Chris Rauer <crauer@google.com>
2
2
3
Trusted Firmware now supports A72 on sbsa-ref by default [1] so enable
3
kudo-bmc is a board supported by OpenBMC.
4
it for QEMU as well. A53 was already enabled there.
4
https://github.com/openbmc/openbmc/tree/master/meta-fii/meta-kudo
5
5
6
1. https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/7117
6
Since v1:
7
- hyphenated Cortex-A9
7
8
8
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
9
Tested: Booted kudo firmware.
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Chris Rauer <crauer@google.com>
10
Message-id: 20201120141705.246690-1-marcin.juszkiewicz@linaro.org
11
Reviewed-by: Patrick Venture <venture@google.com>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20210907223234.1165705-1-crauer@google.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
---
14
hw/arm/sbsa-ref.c | 23 ++++++++++++++++++++---
15
docs/system/arm/nuvoton.rst | 1 +
15
1 file changed, 20 insertions(+), 3 deletions(-)
16
hw/arm/npcm7xx_boards.c | 34 ++++++++++++++++++++++++++++++++++
17
2 files changed, 35 insertions(+)
16
18
17
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
19
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/sbsa-ref.c
21
--- a/docs/system/arm/nuvoton.rst
20
+++ b/hw/arm/sbsa-ref.c
22
+++ b/docs/system/arm/nuvoton.rst
21
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
23
@@ -XXX,XX +XXX,XX @@ Hyperscale applications. The following machines are based on this chip :
22
[SBSA_GWDT] = 16,
24
23
};
25
- ``quanta-gbs-bmc`` Quanta GBS server BMC
24
26
- ``quanta-gsj`` Quanta GSJ server BMC
25
+static const char * const valid_cpus[] = {
27
+- ``kudo-bmc`` Fii USA Kudo server BMC
26
+ ARM_CPU_TYPE_NAME("cortex-a53"),
28
27
+ ARM_CPU_TYPE_NAME("cortex-a57"),
29
There are also two more SoCs, NPCM710 and NPCM705, which are single-core
28
+ ARM_CPU_TYPE_NAME("cortex-a72"),
30
variants of NPCM750 and NPCM730, respectively. These are currently not
31
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/arm/npcm7xx_boards.c
34
+++ b/hw/arm/npcm7xx_boards.c
35
@@ -XXX,XX +XXX,XX @@
36
#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
37
#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
38
#define QUANTA_GBS_POWER_ON_STRAPS 0x000017ff
39
+#define KUDO_BMC_POWER_ON_STRAPS 0x00001fff
40
41
static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
42
43
@@ -XXX,XX +XXX,XX @@ static void quanta_gbs_init(MachineState *machine)
44
npcm7xx_load_kernel(machine, soc);
45
}
46
47
+static void kudo_bmc_init(MachineState *machine)
48
+{
49
+ NPCM7xxState *soc;
50
+
51
+ soc = npcm7xx_create_soc(machine, KUDO_BMC_POWER_ON_STRAPS);
52
+ npcm7xx_connect_dram(soc, machine->ram);
53
+ qdev_realize(DEVICE(soc), NULL, &error_fatal);
54
+
55
+ npcm7xx_load_bootrom(machine, soc);
56
+ npcm7xx_connect_flash(&soc->fiu[0], 0, "mx66u51235f",
57
+ drive_get(IF_MTD, 0, 0));
58
+ npcm7xx_connect_flash(&soc->fiu[1], 0, "mx66u51235f",
59
+ drive_get(IF_MTD, 3, 0));
60
+
61
+ npcm7xx_load_kernel(machine, soc);
62
+}
63
+
64
static void npcm7xx_set_soc_type(NPCM7xxMachineClass *nmc, const char *type)
65
{
66
NPCM7xxClass *sc = NPCM7XX_CLASS(object_class_by_name(type));
67
@@ -XXX,XX +XXX,XX @@ static void gbs_bmc_machine_class_init(ObjectClass *oc, void *data)
68
mc->default_ram_size = 1 * GiB;
69
}
70
71
+static void kudo_bmc_machine_class_init(ObjectClass *oc, void *data)
72
+{
73
+ NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc);
74
+ MachineClass *mc = MACHINE_CLASS(oc);
75
+
76
+ npcm7xx_set_soc_type(nmc, TYPE_NPCM730);
77
+
78
+ mc->desc = "Kudo BMC (Cortex-A9)";
79
+ mc->init = kudo_bmc_init;
80
+ mc->default_ram_size = 1 * GiB;
29
+};
81
+};
30
+
82
+
31
+static bool cpu_type_valid(const char *cpu)
83
static const TypeInfo npcm7xx_machine_types[] = {
32
+{
84
{
33
+ int i;
85
.name = TYPE_NPCM7XX_MACHINE,
34
+
86
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_machine_types[] = {
35
+ for (i = 0; i < ARRAY_SIZE(valid_cpus); i++) {
87
.name = MACHINE_TYPE_NAME("quanta-gbs-bmc"),
36
+ if (strcmp(cpu, valid_cpus[i]) == 0) {
88
.parent = TYPE_NPCM7XX_MACHINE,
37
+ return true;
89
.class_init = gbs_bmc_machine_class_init,
38
+ }
90
+ }, {
39
+ }
91
+ .name = MACHINE_TYPE_NAME("kudo-bmc"),
40
+ return false;
92
+ .parent = TYPE_NPCM7XX_MACHINE,
41
+}
93
+ .class_init = kudo_bmc_machine_class_init,
42
+
94
},
43
static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx)
95
};
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
}
57
96
58
--
97
--
59
2.20.1
98
2.20.1
60
99
61
100
diff view generated by jsdifflib
1
Currently M-profile borrows the A-profile code for VMSR and VMRS
1
From: Shashi Mallela <shashi.mallela@linaro.org>
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
Added register definitions relevant to ITS,implemented overall
7
on read, and one (FPCXT_NS) needs to avoid the usual
4
ITS device framework with stubs for ITS control and translater
8
vfp_access_check() and the "only if FPU implemented" check
5
regions read/write,extended ITS common to handle mmio init between
6
existing kvm device and newer qemu device.
9
7
10
* all sysregs are now accessible both by VMRS/VMSR (which
8
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
11
reads/writes a general purpose register) and also by VLDR/VSTR
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
(which reads/writes them directly to memory)
10
Reviewed-by: Eric Auger <eric.auger@redhat.com>
11
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
12
Message-id: 20210910143951.92242-2-shashi.mallela@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/intc/gicv3_internal.h | 96 +++++++++-
16
include/hw/intc/arm_gicv3_its_common.h | 9 +-
17
hw/intc/arm_gicv3_its.c | 241 +++++++++++++++++++++++++
18
hw/intc/arm_gicv3_its_common.c | 7 +-
19
hw/intc/arm_gicv3_its_kvm.c | 2 +-
20
hw/intc/meson.build | 1 +
21
6 files changed, 342 insertions(+), 14 deletions(-)
22
create mode 100644 hw/intc/arm_gicv3_its.c
13
23
14
Refactor the structure of how we handle VMSR/VMRS to cope with this:
24
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
15
16
* keep the M-profile code entirely separate from the A-profile code
17
18
* abstract out the "read or write the general purpose register" part
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
25
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.h
26
--- a/hw/intc/gicv3_internal.h
33
+++ b/target/arm/cpu.h
27
+++ b/hw/intc/gicv3_internal.h
34
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
28
@@ -XXX,XX +XXX,XX @@
35
#define ARM_VFP_FPINST 9
29
#ifndef QEMU_ARM_GICV3_INTERNAL_H
36
#define ARM_VFP_FPINST2 10
30
#define QEMU_ARM_GICV3_INTERNAL_H
37
31
38
+/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
32
+#include "hw/registerfields.h"
39
+#define QEMU_VFP_FPSCR_NZCV 0xffff
33
#include "hw/intc/arm_gicv3_common.h"
40
+
34
41
/* iwMMXt coprocessor control registers. */
35
/* Distributor registers, as offsets from the distributor base address */
42
#define ARM_IWMMXT_wCID 0
36
@@ -XXX,XX +XXX,XX @@
43
#define ARM_IWMMXT_wCon 1
37
#define GICD_CTLR_E1NWF (1U << 7)
44
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
38
#define GICD_CTLR_RWP (1U << 31)
39
40
+/* 16 bits EventId */
41
+#define GICD_TYPER_IDBITS 0xf
42
+
43
/*
44
* Redistributor frame offsets from RD_base
45
*/
46
@@ -XXX,XX +XXX,XX @@
47
#define GICR_WAKER_ProcessorSleep (1U << 1)
48
#define GICR_WAKER_ChildrenAsleep (1U << 2)
49
50
-#define GICR_PROPBASER_OUTER_CACHEABILITY_MASK (7ULL << 56)
51
-#define GICR_PROPBASER_ADDR_MASK (0xfffffffffULL << 12)
52
-#define GICR_PROPBASER_SHAREABILITY_MASK (3U << 10)
53
-#define GICR_PROPBASER_CACHEABILITY_MASK (7U << 7)
54
-#define GICR_PROPBASER_IDBITS_MASK (0x1f)
55
+FIELD(GICR_PROPBASER, IDBITS, 0, 5)
56
+FIELD(GICR_PROPBASER, INNERCACHE, 7, 3)
57
+FIELD(GICR_PROPBASER, SHAREABILITY, 10, 2)
58
+FIELD(GICR_PROPBASER, PHYADDR, 12, 40)
59
+FIELD(GICR_PROPBASER, OUTERCACHE, 56, 3)
60
61
-#define GICR_PENDBASER_PTZ (1ULL << 62)
62
-#define GICR_PENDBASER_OUTER_CACHEABILITY_MASK (7ULL << 56)
63
-#define GICR_PENDBASER_ADDR_MASK (0xffffffffULL << 16)
64
-#define GICR_PENDBASER_SHAREABILITY_MASK (3U << 10)
65
-#define GICR_PENDBASER_CACHEABILITY_MASK (7U << 7)
66
+FIELD(GICR_PENDBASER, INNERCACHE, 7, 3)
67
+FIELD(GICR_PENDBASER, SHAREABILITY, 10, 2)
68
+FIELD(GICR_PENDBASER, PHYADDR, 16, 36)
69
+FIELD(GICR_PENDBASER, OUTERCACHE, 56, 3)
70
+FIELD(GICR_PENDBASER, PTZ, 62, 1)
71
72
#define ICC_CTLR_EL1_CBPR (1U << 0)
73
#define ICC_CTLR_EL1_EOIMODE (1U << 1)
74
@@ -XXX,XX +XXX,XX @@
75
#define ICH_VTR_EL2_PREBITS_SHIFT 26
76
#define ICH_VTR_EL2_PRIBITS_SHIFT 29
77
78
+/* ITS Registers */
79
+
80
+FIELD(GITS_BASER, SIZE, 0, 8)
81
+FIELD(GITS_BASER, PAGESIZE, 8, 2)
82
+FIELD(GITS_BASER, SHAREABILITY, 10, 2)
83
+FIELD(GITS_BASER, PHYADDR, 12, 36)
84
+FIELD(GITS_BASER, PHYADDRL_64K, 16, 32)
85
+FIELD(GITS_BASER, PHYADDRH_64K, 12, 4)
86
+FIELD(GITS_BASER, ENTRYSIZE, 48, 5)
87
+FIELD(GITS_BASER, OUTERCACHE, 53, 3)
88
+FIELD(GITS_BASER, TYPE, 56, 3)
89
+FIELD(GITS_BASER, INNERCACHE, 59, 3)
90
+FIELD(GITS_BASER, INDIRECT, 62, 1)
91
+FIELD(GITS_BASER, VALID, 63, 1)
92
+
93
+FIELD(GITS_CTLR, QUIESCENT, 31, 1)
94
+
95
+FIELD(GITS_TYPER, PHYSICAL, 0, 1)
96
+FIELD(GITS_TYPER, ITT_ENTRY_SIZE, 4, 4)
97
+FIELD(GITS_TYPER, IDBITS, 8, 5)
98
+FIELD(GITS_TYPER, DEVBITS, 13, 5)
99
+FIELD(GITS_TYPER, SEIS, 18, 1)
100
+FIELD(GITS_TYPER, PTA, 19, 1)
101
+FIELD(GITS_TYPER, CIDBITS, 32, 4)
102
+FIELD(GITS_TYPER, CIL, 36, 1)
103
+
104
+#define GITS_BASER_PAGESIZE_4K 0
105
+#define GITS_BASER_PAGESIZE_16K 1
106
+#define GITS_BASER_PAGESIZE_64K 2
107
+
108
+#define GITS_BASER_TYPE_DEVICE 1ULL
109
+#define GITS_BASER_TYPE_COLLECTION 4ULL
110
+
111
+/**
112
+ * Default features advertised by this version of ITS
113
+ */
114
+/* Physical LPIs supported */
115
+#define GITS_TYPE_PHYSICAL (1U << 0)
116
+
117
+/*
118
+ * 12 bytes Interrupt translation Table Entry size
119
+ * as per Table 5.3 in GICv3 spec
120
+ * ITE Lower 8 Bytes
121
+ * Bits: | 49 ... 26 | 25 ... 2 | 1 | 0 |
122
+ * Values: | 1023 | IntNum | IntType | Valid |
123
+ * ITE Higher 4 Bytes
124
+ * Bits: | 31 ... 16 | 15 ...0 |
125
+ * Values: | vPEID | ICID |
126
+ */
127
+#define ITS_ITT_ENTRY_SIZE 0xC
128
+
129
+/* 16 bits EventId */
130
+#define ITS_IDBITS GICD_TYPER_IDBITS
131
+
132
+/* 16 bits DeviceId */
133
+#define ITS_DEVBITS 0xF
134
+
135
+/* 16 bits CollectionId */
136
+#define ITS_CIDBITS 0xF
137
+
138
+/*
139
+ * 8 bytes Device Table Entry size
140
+ * Valid = 1 bit,ITTAddr = 44 bits,Size = 5 bits
141
+ */
142
+#define GITS_DTE_SIZE (0x8ULL)
143
+
144
+/*
145
+ * 8 bytes Collection Table Entry size
146
+ * Valid = 1 bit,RDBase = 36 bits(considering max RDBASE)
147
+ */
148
+#define GITS_CTE_SIZE (0x8ULL)
149
+
150
/* Special interrupt IDs */
151
#define INTID_SECURE 1020
152
#define INTID_NONSECURE 1021
153
diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h
45
index XXXXXXX..XXXXXXX 100644
154
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/translate-vfp.c.inc
155
--- a/include/hw/intc/arm_gicv3_its_common.h
47
+++ b/target/arm/translate-vfp.c.inc
156
+++ b/include/hw/intc/arm_gicv3_its_common.h
48
@@ -XXX,XX +XXX,XX @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
157
@@ -XXX,XX +XXX,XX @@
49
return true;
158
#include "hw/intc/arm_gicv3_common.h"
50
}
159
#include "qom/object.h"
51
160
161
+#define TYPE_ARM_GICV3_ITS "arm-gicv3-its"
162
+
163
#define ITS_CONTROL_SIZE 0x10000
164
#define ITS_TRANS_SIZE 0x10000
165
#define ITS_SIZE (ITS_CONTROL_SIZE + ITS_TRANS_SIZE)
166
167
#define GITS_CTLR 0x0
168
#define GITS_IIDR 0x4
169
+#define GITS_TYPER 0x8
170
#define GITS_CBASER 0x80
171
#define GITS_CWRITER 0x88
172
#define GITS_CREADR 0x90
173
#define GITS_BASER 0x100
174
175
+#define GITS_TRANSLATER 0x0040
176
+
177
struct GICv3ITSState {
178
SysBusDevice parent_obj;
179
180
@@ -XXX,XX +XXX,XX @@ struct GICv3ITSState {
181
/* Registers */
182
uint32_t ctlr;
183
uint32_t iidr;
184
+ uint64_t typer;
185
uint64_t cbaser;
186
uint64_t cwriter;
187
uint64_t creadr;
188
@@ -XXX,XX +XXX,XX @@ struct GICv3ITSState {
189
190
typedef struct GICv3ITSState GICv3ITSState;
191
192
-void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops);
193
+void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops,
194
+ const MemoryRegionOps *tops);
195
196
#define TYPE_ARM_GICV3_ITS_COMMON "arm-gicv3-its-common"
197
typedef struct GICv3ITSCommonClass GICv3ITSCommonClass;
198
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
199
new file mode 100644
200
index XXXXXXX..XXXXXXX
201
--- /dev/null
202
+++ b/hw/intc/arm_gicv3_its.c
203
@@ -XXX,XX +XXX,XX @@
52
+/*
204
+/*
53
+ * M-profile provides two different sets of instructions that can
205
+ * ITS emulation for a GICv3-based system
54
+ * access floating point system registers: VMSR/VMRS (which move
206
+ *
55
+ * to/from a general purpose register) and VLDR/VSTR sysreg (which
207
+ * Copyright Linaro.org 2021
56
+ * move directly to/from memory). In some cases there are also side
208
+ *
57
+ * effects which must happen after any write to memory (which could
209
+ * Authors:
58
+ * cause an exception). So we implement the common logic for the
210
+ * Shashi Mallela <shashi.mallela@linaro.org>
59
+ * sysreg access in gen_M_fp_sysreg_write() and gen_M_fp_sysreg_read(),
211
+ *
60
+ * which take pointers to callback functions which will perform the
212
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
61
+ * actual "read/write general purpose register" and "read/write
213
+ * option) any later version. See the COPYING file in the top-level directory.
62
+ * memory" operations.
214
+ *
63
+ */
215
+ */
64
+
216
+
65
+/*
217
+#include "qemu/osdep.h"
66
+ * Emit code to store the sysreg to its final destination; frees the
218
+#include "qemu/log.h"
67
+ * TCG temp 'value' it is passed.
219
+#include "hw/qdev-properties.h"
68
+ */
220
+#include "hw/intc/arm_gicv3_its_common.h"
69
+typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
221
+#include "gicv3_internal.h"
70
+/*
222
+#include "qom/object.h"
71
+ * Emit code to load the value to be copied to the sysreg; returns
223
+#include "qapi/error.h"
72
+ * a new TCG temporary
224
+
73
+ */
225
+typedef struct GICv3ITSClass GICv3ITSClass;
74
+typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
226
+/* This is reusing the GICv3ITSState typedef from ARM_GICV3_ITS_COMMON */
75
+
227
+DECLARE_OBJ_CHECKERS(GICv3ITSState, GICv3ITSClass,
76
+/* Common decode/access checks for fp sysreg read/write */
228
+ ARM_GICV3_ITS, TYPE_ARM_GICV3_ITS)
77
+typedef enum FPSysRegCheckResult {
229
+
78
+ FPSysRegCheckFailed, /* caller should return false */
230
+struct GICv3ITSClass {
79
+ FPSysRegCheckDone, /* caller should return true */
231
+ GICv3ITSCommonClass parent_class;
80
+ FPSysRegCheckContinue, /* caller should continue generating code */
232
+ void (*parent_reset)(DeviceState *dev);
81
+} FPSysRegCheckResult;
233
+};
82
+
234
+
83
+static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
235
+static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
84
+{
236
+ uint64_t data, unsigned size,
85
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
237
+ MemTxAttrs attrs)
86
+ return FPSysRegCheckFailed;
238
+{
87
+ }
239
+ return MEMTX_OK;
88
+
240
+}
89
+ switch (regno) {
241
+
90
+ case ARM_VFP_FPSCR:
242
+static bool its_writel(GICv3ITSState *s, hwaddr offset,
91
+ case QEMU_VFP_FPSCR_NZCV:
243
+ uint64_t value, MemTxAttrs attrs)
244
+{
245
+ bool result = true;
246
+
247
+ return result;
248
+}
249
+
250
+static bool its_readl(GICv3ITSState *s, hwaddr offset,
251
+ uint64_t *data, MemTxAttrs attrs)
252
+{
253
+ bool result = true;
254
+
255
+ return result;
256
+}
257
+
258
+static bool its_writell(GICv3ITSState *s, hwaddr offset,
259
+ uint64_t value, MemTxAttrs attrs)
260
+{
261
+ bool result = true;
262
+
263
+ return result;
264
+}
265
+
266
+static bool its_readll(GICv3ITSState *s, hwaddr offset,
267
+ uint64_t *data, MemTxAttrs attrs)
268
+{
269
+ bool result = true;
270
+
271
+ return result;
272
+}
273
+
274
+static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data,
275
+ unsigned size, MemTxAttrs attrs)
276
+{
277
+ GICv3ITSState *s = (GICv3ITSState *)opaque;
278
+ bool result;
279
+
280
+ switch (size) {
281
+ case 4:
282
+ result = its_readl(s, offset, data, attrs);
283
+ break;
284
+ case 8:
285
+ result = its_readll(s, offset, data, attrs);
92
+ break;
286
+ break;
93
+ default:
287
+ default:
94
+ return FPSysRegCheckFailed;
288
+ result = false;
95
+ }
96
+
97
+ if (!vfp_access_check(s)) {
98
+ return FPSysRegCheckDone;
99
+ }
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;
289
+ break;
119
+ }
290
+ }
120
+
291
+
121
+ switch (regno) {
292
+ if (!result) {
122
+ case ARM_VFP_FPSCR:
293
+ qemu_log_mask(LOG_GUEST_ERROR,
123
+ tmp = loadfn(s, opaque);
294
+ "%s: invalid guest read at offset " TARGET_FMT_plx
124
+ gen_helper_vfp_set_fpscr(cpu_env, tmp);
295
+ "size %u\n", __func__, offset, size);
125
+ tcg_temp_free_i32(tmp);
296
+ /*
126
+ gen_lookup_tb(s);
297
+ * The spec requires that reserved registers are RAZ/WI;
298
+ * so use false returns from leaf functions as a way to
299
+ * trigger the guest-error logging but don't return it to
300
+ * the caller, or we'll cause a spurious guest data abort.
301
+ */
302
+ *data = 0;
303
+ }
304
+ return MEMTX_OK;
305
+}
306
+
307
+static MemTxResult gicv3_its_write(void *opaque, hwaddr offset, uint64_t data,
308
+ unsigned size, MemTxAttrs attrs)
309
+{
310
+ GICv3ITSState *s = (GICv3ITSState *)opaque;
311
+ bool result;
312
+
313
+ switch (size) {
314
+ case 4:
315
+ result = its_writel(s, offset, data, attrs);
316
+ break;
317
+ case 8:
318
+ result = its_writell(s, offset, data, attrs);
127
+ break;
319
+ break;
128
+ default:
320
+ default:
129
+ g_assert_not_reached();
321
+ result = false;
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;
322
+ break;
148
+ }
323
+ }
149
+
324
+
150
+ switch (regno) {
325
+ if (!result) {
151
+ case ARM_VFP_FPSCR:
326
+ qemu_log_mask(LOG_GUEST_ERROR,
152
+ tmp = tcg_temp_new_i32();
327
+ "%s: invalid guest write at offset " TARGET_FMT_plx
153
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
328
+ "size %u\n", __func__, offset, size);
154
+ storefn(s, opaque, tmp);
155
+ break;
156
+ case QEMU_VFP_FPSCR_NZCV:
157
+ /*
329
+ /*
158
+ * Read just NZCV; this is a special case to avoid the
330
+ * The spec requires that reserved registers are RAZ/WI;
159
+ * helper call for the "VMRS to CPSR.NZCV" insn.
331
+ * so use false returns from leaf functions as a way to
332
+ * trigger the guest-error logging but don't return it to
333
+ * the caller, or we'll cause a spurious guest data abort.
160
+ */
334
+ */
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
+ }
335
+ }
168
+ return true;
336
+ return MEMTX_OK;
169
+}
337
+}
170
+
338
+
171
+static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
339
+static const MemoryRegionOps gicv3_its_control_ops = {
172
+{
340
+ .read_with_attrs = gicv3_its_read,
173
+ arg_VMSR_VMRS *a = opaque;
341
+ .write_with_attrs = gicv3_its_write,
174
+
342
+ .valid.min_access_size = 4,
175
+ if (a->rt == 15) {
343
+ .valid.max_access_size = 8,
176
+ /* Set the 4 flag bits in the CPSR */
344
+ .impl.min_access_size = 4,
177
+ gen_set_nzcv(value);
345
+ .impl.max_access_size = 8,
178
+ tcg_temp_free_i32(value);
346
+ .endianness = DEVICE_NATIVE_ENDIAN,
179
+ } else {
347
+};
180
+ store_reg(s, a->rt, value);
348
+
181
+ }
349
+static const MemoryRegionOps gicv3_its_translation_ops = {
182
+}
350
+ .write_with_attrs = gicv3_its_translation_write,
183
+
351
+ .valid.min_access_size = 2,
184
+static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
352
+ .valid.max_access_size = 4,
185
+{
353
+ .impl.min_access_size = 2,
186
+ arg_VMSR_VMRS *a = opaque;
354
+ .impl.max_access_size = 4,
187
+
355
+ .endianness = DEVICE_NATIVE_ENDIAN,
188
+ return load_reg(s, a->rt);
356
+};
189
+}
357
+
190
+
358
+static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
191
+static bool gen_M_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
359
+{
192
+{
360
+ GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
193
+ /*
361
+ int i;
194
+ * Accesses to R15 are UNPREDICTABLE; we choose to undef.
362
+
195
+ * FPSCR -> r15 is a special case which writes to the PSR flags;
363
+ for (i = 0; i < s->gicv3->num_cpu; i++) {
196
+ * set a->reg to a special value to tell gen_M_fp_sysreg_read()
364
+ if (!(s->gicv3->cpu[i].gicr_typer & GICR_TYPER_PLPIS)) {
197
+ * we only care about the top 4 bits of FPSCR there.
365
+ error_setg(errp, "Physical LPI not supported by CPU %d", i);
198
+ */
366
+ return;
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
+ }
367
+ }
205
+ }
368
+ }
206
+
369
+
207
+ if (a->l) {
370
+ gicv3_its_init_mmio(s, &gicv3_its_control_ops, &gicv3_its_translation_ops);
208
+ /* VMRS, move FP system register to gp register */
371
+
209
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_gpr, a);
372
+ /* set the ITS default features supported */
210
+ } else {
373
+ s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL,
211
+ /* VMSR, move gp register to FP system register */
374
+ GITS_TYPE_PHYSICAL);
212
+ return gen_M_fp_sysreg_write(s, a->reg, gpr_to_fp_sysreg, a);
375
+ s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE,
213
+ }
376
+ ITS_ITT_ENTRY_SIZE - 1);
214
+}
377
+ s->typer = FIELD_DP64(s->typer, GITS_TYPER, IDBITS, ITS_IDBITS);
215
+
378
+ s->typer = FIELD_DP64(s->typer, GITS_TYPER, DEVBITS, ITS_DEVBITS);
216
static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
379
+ s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIL, 1);
380
+ s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIDBITS, ITS_CIDBITS);
381
+}
382
+
383
+static void gicv3_its_reset(DeviceState *dev)
384
+{
385
+ GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
386
+ GICv3ITSClass *c = ARM_GICV3_ITS_GET_CLASS(s);
387
+
388
+ c->parent_reset(dev);
389
+
390
+ /* Quiescent bit reset to 1 */
391
+ s->ctlr = FIELD_DP32(s->ctlr, GITS_CTLR, QUIESCENT, 1);
392
+
393
+ /*
394
+ * setting GITS_BASER0.Type = 0b001 (Device)
395
+ * GITS_BASER1.Type = 0b100 (Collection Table)
396
+ * GITS_BASER<n>.Type,where n = 3 to 7 are 0b00 (Unimplemented)
397
+ * GITS_BASER<0,1>.Page_Size = 64KB
398
+ * and default translation table entry size to 16 bytes
399
+ */
400
+ s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, TYPE,
401
+ GITS_BASER_TYPE_DEVICE);
402
+ s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, PAGESIZE,
403
+ GITS_BASER_PAGESIZE_64K);
404
+ s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, ENTRYSIZE,
405
+ GITS_DTE_SIZE - 1);
406
+
407
+ s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, TYPE,
408
+ GITS_BASER_TYPE_COLLECTION);
409
+ s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, PAGESIZE,
410
+ GITS_BASER_PAGESIZE_64K);
411
+ s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, ENTRYSIZE,
412
+ GITS_CTE_SIZE - 1);
413
+}
414
+
415
+static Property gicv3_its_props[] = {
416
+ DEFINE_PROP_LINK("parent-gicv3", GICv3ITSState, gicv3, "arm-gicv3",
417
+ GICv3State *),
418
+ DEFINE_PROP_END_OF_LIST(),
419
+};
420
+
421
+static void gicv3_its_class_init(ObjectClass *klass, void *data)
422
+{
423
+ DeviceClass *dc = DEVICE_CLASS(klass);
424
+ GICv3ITSClass *ic = ARM_GICV3_ITS_CLASS(klass);
425
+
426
+ dc->realize = gicv3_arm_its_realize;
427
+ device_class_set_props(dc, gicv3_its_props);
428
+ device_class_set_parent_reset(dc, gicv3_its_reset, &ic->parent_reset);
429
+}
430
+
431
+static const TypeInfo gicv3_its_info = {
432
+ .name = TYPE_ARM_GICV3_ITS,
433
+ .parent = TYPE_ARM_GICV3_ITS_COMMON,
434
+ .instance_size = sizeof(GICv3ITSState),
435
+ .class_init = gicv3_its_class_init,
436
+ .class_size = sizeof(GICv3ITSClass),
437
+};
438
+
439
+static void gicv3_its_register_types(void)
440
+{
441
+ type_register_static(&gicv3_its_info);
442
+}
443
+
444
+type_init(gicv3_its_register_types)
445
diff --git a/hw/intc/arm_gicv3_its_common.c b/hw/intc/arm_gicv3_its_common.c
446
index XXXXXXX..XXXXXXX 100644
447
--- a/hw/intc/arm_gicv3_its_common.c
448
+++ b/hw/intc/arm_gicv3_its_common.c
449
@@ -XXX,XX +XXX,XX @@ static int gicv3_its_post_load(void *opaque, int version_id)
450
451
static const VMStateDescription vmstate_its = {
452
.name = "arm_gicv3_its",
453
+ .version_id = 1,
454
+ .minimum_version_id = 1,
455
.pre_save = gicv3_its_pre_save,
456
.post_load = gicv3_its_post_load,
457
.priority = MIG_PRI_GICV3_ITS,
458
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps gicv3_its_trans_ops = {
459
.endianness = DEVICE_NATIVE_ENDIAN,
460
};
461
462
-void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops)
463
+void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops,
464
+ const MemoryRegionOps *tops)
217
{
465
{
218
TCGv_i32 tmp;
466
SysBusDevice *sbd = SYS_BUS_DEVICE(s);
219
bool ignore_vfp_enabled = false;
467
220
468
memory_region_init_io(&s->iomem_its_cntrl, OBJECT(s), ops, s,
221
- if (!dc_isar_feature(aa32_fpsp_v2, s)) {
469
"control", ITS_CONTROL_SIZE);
222
- return false;
470
memory_region_init_io(&s->iomem_its_translation, OBJECT(s),
223
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
471
- &gicv3_its_trans_ops, s,
224
+ return gen_M_VMSR_VMRS(s, a);
472
+ tops ? tops : &gicv3_its_trans_ops, s,
225
}
473
"translation", ITS_TRANS_SIZE);
226
474
227
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
475
/* Our two regions are always adjacent, therefore we now combine them
228
- /*
476
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
229
- * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
477
index XXXXXXX..XXXXXXX 100644
230
- * Accesses to R15 are UNPREDICTABLE; we choose to undef.
478
--- a/hw/intc/arm_gicv3_its_kvm.c
231
- * (FPSCR -> r15 is a special case which writes to the PSR flags.)
479
+++ b/hw/intc/arm_gicv3_its_kvm.c
232
- */
480
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
233
- if (a->reg != ARM_VFP_FPSCR) {
481
kvm_arm_register_device(&s->iomem_its_cntrl, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
234
- return false;
482
KVM_VGIC_ITS_ADDR_TYPE, s->dev_fd, 0);
235
- }
483
236
- if (a->rt == 15 && !a->l) {
484
- gicv3_its_init_mmio(s, NULL);
237
- return false;
485
+ gicv3_its_init_mmio(s, NULL, NULL);
238
- }
486
239
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
487
if (!kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
240
+ return false;
488
GITS_CTLR)) {
241
}
489
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
242
490
index XXXXXXX..XXXXXXX 100644
243
switch (a->reg) {
491
--- a/hw/intc/meson.build
492
+++ b/hw/intc/meson.build
493
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_ARM_GIC', if_true: files(
494
'arm_gicv3_dist.c',
495
'arm_gicv3_its_common.c',
496
'arm_gicv3_redist.c',
497
+ 'arm_gicv3_its.c',
498
))
499
softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_pic.c'))
500
softmmu_ss.add(when: 'CONFIG_HEATHROW_PIC', if_true: files('heathrow_pic.c'))
244
--
501
--
245
2.20.1
502
2.20.1
246
503
247
504
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
2
3
Dump the collected random data after a randomness test failure.
3
Defined descriptors for ITS device table,collection table and ITS
4
command queue entities.Implemented register read/write functions,
5
extract ITS table parameters and command queue parameters,extended
6
gicv3 common to capture qemu address space(which host the ITS table
7
platform memories required for subsequent ITS processing) and
8
initialize the same in ITS device.
4
9
5
Note that this relies on the test having called
10
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
6
g_test_set_nonfatal_assertions() so we don't abort immediately on the
7
assertion failure.
8
9
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
[PMM: minor commit message tweak]
12
Reviewed-by: Eric Auger <eric.auger@redhat.com>
13
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
14
Message-id: 20210910143951.92242-3-shashi.mallela@linaro.org
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
hw/intc/gicv3_internal.h | 29 ++
15
1 file changed, 12 insertions(+)
18
include/hw/intc/arm_gicv3_common.h | 3 +
19
include/hw/intc/arm_gicv3_its_common.h | 23 ++
20
hw/intc/arm_gicv3_its.c | 376 +++++++++++++++++++++++++
21
4 files changed, 431 insertions(+)
16
22
17
diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c
23
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
18
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qtest/npcm7xx_rng-test.c
25
--- a/hw/intc/gicv3_internal.h
20
+++ b/tests/qtest/npcm7xx_rng-test.c
26
+++ b/hw/intc/gicv3_internal.h
27
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_BASER, INNERCACHE, 59, 3)
28
FIELD(GITS_BASER, INDIRECT, 62, 1)
29
FIELD(GITS_BASER, VALID, 63, 1)
30
31
+FIELD(GITS_CBASER, SIZE, 0, 8)
32
+FIELD(GITS_CBASER, SHAREABILITY, 10, 2)
33
+FIELD(GITS_CBASER, PHYADDR, 12, 40)
34
+FIELD(GITS_CBASER, OUTERCACHE, 53, 3)
35
+FIELD(GITS_CBASER, INNERCACHE, 59, 3)
36
+FIELD(GITS_CBASER, VALID, 63, 1)
37
+
38
+FIELD(GITS_CREADR, STALLED, 0, 1)
39
+FIELD(GITS_CREADR, OFFSET, 5, 15)
40
+
41
+FIELD(GITS_CWRITER, RETRY, 0, 1)
42
+FIELD(GITS_CWRITER, OFFSET, 5, 15)
43
+
44
+FIELD(GITS_CTLR, ENABLED, 0, 1)
45
FIELD(GITS_CTLR, QUIESCENT, 31, 1)
46
47
FIELD(GITS_TYPER, PHYSICAL, 0, 1)
48
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, PTA, 19, 1)
49
FIELD(GITS_TYPER, CIDBITS, 32, 4)
50
FIELD(GITS_TYPER, CIL, 36, 1)
51
52
+#define GITS_IDREGS 0xFFD0
53
+
54
+#define ITS_CTLR_ENABLED (1U) /* ITS Enabled */
55
+
56
+#define GITS_BASER_RO_MASK (R_GITS_BASER_ENTRYSIZE_MASK | \
57
+ R_GITS_BASER_TYPE_MASK)
58
+
59
#define GITS_BASER_PAGESIZE_4K 0
60
#define GITS_BASER_PAGESIZE_16K 1
61
#define GITS_BASER_PAGESIZE_64K 2
62
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
63
#define GITS_BASER_TYPE_DEVICE 1ULL
64
#define GITS_BASER_TYPE_COLLECTION 4ULL
65
66
+#define GITS_PAGE_SIZE_4K 0x1000
67
+#define GITS_PAGE_SIZE_16K 0x4000
68
+#define GITS_PAGE_SIZE_64K 0x10000
69
+
70
+#define L1TABLE_ENTRY_SIZE 8
71
+
72
+#define GITS_CMDQ_ENTRY_SIZE 32
73
+
74
/**
75
* Default features advertised by this version of ITS
76
*/
77
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
78
index XXXXXXX..XXXXXXX 100644
79
--- a/include/hw/intc/arm_gicv3_common.h
80
+++ b/include/hw/intc/arm_gicv3_common.h
81
@@ -XXX,XX +XXX,XX @@ struct GICv3State {
82
int dev_fd; /* kvm device fd if backed by kvm vgic support */
83
Error *migration_blocker;
84
85
+ MemoryRegion *dma;
86
+ AddressSpace dma_as;
87
+
88
/* Distributor */
89
90
/* for a GIC with the security extensions the NS banked version of this
91
diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h
92
index XXXXXXX..XXXXXXX 100644
93
--- a/include/hw/intc/arm_gicv3_its_common.h
94
+++ b/include/hw/intc/arm_gicv3_its_common.h
21
@@ -XXX,XX +XXX,XX @@
95
@@ -XXX,XX +XXX,XX @@
22
96
23
#include "libqtest-single.h"
97
#define GITS_TRANSLATER 0x0040
24
#include "qemu/bitops.h"
98
25
+#include "qemu-common.h"
99
+typedef struct {
26
100
+ bool valid;
27
#define RNG_BASE_ADDR 0xf000b000
101
+ bool indirect;
28
102
+ uint16_t entry_sz;
29
@@ -XXX,XX +XXX,XX @@
103
+ uint32_t page_sz;
30
/* Number of bits to collect for randomness tests. */
104
+ uint32_t max_entries;
31
#define TEST_INPUT_BITS (128)
105
+ union {
32
106
+ uint32_t max_devids;
33
+static void dump_buf_if_failed(const uint8_t *buf, size_t size)
107
+ uint32_t max_collids;
108
+ } maxids;
109
+ uint64_t base_addr;
110
+} TableDesc;
111
+
112
+typedef struct {
113
+ bool valid;
114
+ uint32_t max_entries;
115
+ uint64_t base_addr;
116
+} CmdQDesc;
117
+
118
struct GICv3ITSState {
119
SysBusDevice parent_obj;
120
121
@@ -XXX,XX +XXX,XX @@ struct GICv3ITSState {
122
uint64_t creadr;
123
uint64_t baser[8];
124
125
+ TableDesc dt;
126
+ TableDesc ct;
127
+ CmdQDesc cq;
128
+
129
Error *migration_blocker;
130
};
131
132
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
133
index XXXXXXX..XXXXXXX 100644
134
--- a/hw/intc/arm_gicv3_its.c
135
+++ b/hw/intc/arm_gicv3_its.c
136
@@ -XXX,XX +XXX,XX @@ struct GICv3ITSClass {
137
void (*parent_reset)(DeviceState *dev);
138
};
139
140
+static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
34
+{
141
+{
35
+ if (g_test_failed()) {
142
+ uint64_t result = 0;
36
+ qemu_hexdump(stderr, "", buf, size);
143
+
37
+ }
144
+ switch (page_sz) {
145
+ case GITS_PAGE_SIZE_4K:
146
+ case GITS_PAGE_SIZE_16K:
147
+ result = FIELD_EX64(value, GITS_BASER, PHYADDR) << 12;
148
+ break;
149
+
150
+ case GITS_PAGE_SIZE_64K:
151
+ result = FIELD_EX64(value, GITS_BASER, PHYADDRL_64K) << 16;
152
+ result |= FIELD_EX64(value, GITS_BASER, PHYADDRH_64K) << 48;
153
+ break;
154
+
155
+ default:
156
+ break;
157
+ }
158
+ return result;
38
+}
159
+}
39
+
160
+
40
static void rng_writeb(unsigned int offset, uint8_t value)
161
+/*
162
+ * This function extracts the ITS Device and Collection table specific
163
+ * parameters (like base_addr, size etc) from GITS_BASER register.
164
+ * It is called during ITS enable and also during post_load migration
165
+ */
166
+static void extract_table_params(GICv3ITSState *s)
167
+{
168
+ uint16_t num_pages = 0;
169
+ uint8_t page_sz_type;
170
+ uint8_t type;
171
+ uint32_t page_sz = 0;
172
+ uint64_t value;
173
+
174
+ for (int i = 0; i < 8; i++) {
175
+ value = s->baser[i];
176
+
177
+ if (!value) {
178
+ continue;
179
+ }
180
+
181
+ page_sz_type = FIELD_EX64(value, GITS_BASER, PAGESIZE);
182
+
183
+ switch (page_sz_type) {
184
+ case 0:
185
+ page_sz = GITS_PAGE_SIZE_4K;
186
+ break;
187
+
188
+ case 1:
189
+ page_sz = GITS_PAGE_SIZE_16K;
190
+ break;
191
+
192
+ case 2:
193
+ case 3:
194
+ page_sz = GITS_PAGE_SIZE_64K;
195
+ break;
196
+
197
+ default:
198
+ g_assert_not_reached();
199
+ }
200
+
201
+ num_pages = FIELD_EX64(value, GITS_BASER, SIZE) + 1;
202
+
203
+ type = FIELD_EX64(value, GITS_BASER, TYPE);
204
+
205
+ switch (type) {
206
+
207
+ case GITS_BASER_TYPE_DEVICE:
208
+ memset(&s->dt, 0 , sizeof(s->dt));
209
+ s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID);
210
+
211
+ if (!s->dt.valid) {
212
+ return;
213
+ }
214
+
215
+ s->dt.page_sz = page_sz;
216
+ s->dt.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
217
+ s->dt.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
218
+
219
+ if (!s->dt.indirect) {
220
+ s->dt.max_entries = (num_pages * page_sz) / s->dt.entry_sz;
221
+ } else {
222
+ s->dt.max_entries = (((num_pages * page_sz) /
223
+ L1TABLE_ENTRY_SIZE) *
224
+ (page_sz / s->dt.entry_sz));
225
+ }
226
+
227
+ s->dt.maxids.max_devids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER,
228
+ DEVBITS) + 1));
229
+
230
+ s->dt.base_addr = baser_base_addr(value, page_sz);
231
+
232
+ break;
233
+
234
+ case GITS_BASER_TYPE_COLLECTION:
235
+ memset(&s->ct, 0 , sizeof(s->ct));
236
+ s->ct.valid = FIELD_EX64(value, GITS_BASER, VALID);
237
+
238
+ /*
239
+ * GITS_TYPER.HCC is 0 for this implementation
240
+ * hence writes are discarded if ct.valid is 0
241
+ */
242
+ if (!s->ct.valid) {
243
+ return;
244
+ }
245
+
246
+ s->ct.page_sz = page_sz;
247
+ s->ct.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
248
+ s->ct.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
249
+
250
+ if (!s->ct.indirect) {
251
+ s->ct.max_entries = (num_pages * page_sz) / s->ct.entry_sz;
252
+ } else {
253
+ s->ct.max_entries = (((num_pages * page_sz) /
254
+ L1TABLE_ENTRY_SIZE) *
255
+ (page_sz / s->ct.entry_sz));
256
+ }
257
+
258
+ if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) {
259
+ s->ct.maxids.max_collids = (1UL << (FIELD_EX64(s->typer,
260
+ GITS_TYPER, CIDBITS) + 1));
261
+ } else {
262
+ /* 16-bit CollectionId supported when CIL == 0 */
263
+ s->ct.maxids.max_collids = (1UL << 16);
264
+ }
265
+
266
+ s->ct.base_addr = baser_base_addr(value, page_sz);
267
+
268
+ break;
269
+
270
+ default:
271
+ break;
272
+ }
273
+ }
274
+}
275
+
276
+static void extract_cmdq_params(GICv3ITSState *s)
277
+{
278
+ uint16_t num_pages = 0;
279
+ uint64_t value = s->cbaser;
280
+
281
+ num_pages = FIELD_EX64(value, GITS_CBASER, SIZE) + 1;
282
+
283
+ memset(&s->cq, 0 , sizeof(s->cq));
284
+ s->cq.valid = FIELD_EX64(value, GITS_CBASER, VALID);
285
+
286
+ if (s->cq.valid) {
287
+ s->cq.max_entries = (num_pages * GITS_PAGE_SIZE_4K) /
288
+ GITS_CMDQ_ENTRY_SIZE;
289
+ s->cq.base_addr = FIELD_EX64(value, GITS_CBASER, PHYADDR);
290
+ s->cq.base_addr <<= R_GITS_CBASER_PHYADDR_SHIFT;
291
+ }
292
+}
293
+
294
static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
295
uint64_t data, unsigned size,
296
MemTxAttrs attrs)
297
@@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
298
uint64_t value, MemTxAttrs attrs)
41
{
299
{
42
writeb(RNG_BASE_ADDR + offset, value);
300
bool result = true;
43
@@ -XXX,XX +XXX,XX @@ static void test_continuous_monobit(void)
301
+ int index;
44
}
302
45
303
+ switch (offset) {
46
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
304
+ case GITS_CTLR:
47
+ dump_buf_if_failed(buf, sizeof(buf));
305
+ s->ctlr |= (value & ~(s->ctlr));
306
+
307
+ if (s->ctlr & ITS_CTLR_ENABLED) {
308
+ extract_table_params(s);
309
+ extract_cmdq_params(s);
310
+ s->creadr = 0;
311
+ }
312
+ break;
313
+ case GITS_CBASER:
314
+ /*
315
+ * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
316
+ * already enabled
317
+ */
318
+ if (!(s->ctlr & ITS_CTLR_ENABLED)) {
319
+ s->cbaser = deposit64(s->cbaser, 0, 32, value);
320
+ s->creadr = 0;
321
+ s->cwriter = s->creadr;
322
+ }
323
+ break;
324
+ case GITS_CBASER + 4:
325
+ /*
326
+ * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
327
+ * already enabled
328
+ */
329
+ if (!(s->ctlr & ITS_CTLR_ENABLED)) {
330
+ s->cbaser = deposit64(s->cbaser, 32, 32, value);
331
+ s->creadr = 0;
332
+ s->cwriter = s->creadr;
333
+ }
334
+ break;
335
+ case GITS_CWRITER:
336
+ s->cwriter = deposit64(s->cwriter, 0, 32,
337
+ (value & ~R_GITS_CWRITER_RETRY_MASK));
338
+ break;
339
+ case GITS_CWRITER + 4:
340
+ s->cwriter = deposit64(s->cwriter, 32, 32, value);
341
+ break;
342
+ case GITS_CREADR:
343
+ if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
344
+ s->creadr = deposit64(s->creadr, 0, 32,
345
+ (value & ~R_GITS_CREADR_STALLED_MASK));
346
+ } else {
347
+ /* RO register, ignore the write */
348
+ qemu_log_mask(LOG_GUEST_ERROR,
349
+ "%s: invalid guest write to RO register at offset "
350
+ TARGET_FMT_plx "\n", __func__, offset);
351
+ }
352
+ break;
353
+ case GITS_CREADR + 4:
354
+ if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
355
+ s->creadr = deposit64(s->creadr, 32, 32, value);
356
+ } else {
357
+ /* RO register, ignore the write */
358
+ qemu_log_mask(LOG_GUEST_ERROR,
359
+ "%s: invalid guest write to RO register at offset "
360
+ TARGET_FMT_plx "\n", __func__, offset);
361
+ }
362
+ break;
363
+ case GITS_BASER ... GITS_BASER + 0x3f:
364
+ /*
365
+ * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
366
+ * already enabled
367
+ */
368
+ if (!(s->ctlr & ITS_CTLR_ENABLED)) {
369
+ index = (offset - GITS_BASER) / 8;
370
+
371
+ if (offset & 7) {
372
+ value <<= 32;
373
+ value &= ~GITS_BASER_RO_MASK;
374
+ s->baser[index] &= GITS_BASER_RO_MASK | MAKE_64BIT_MASK(0, 32);
375
+ s->baser[index] |= value;
376
+ } else {
377
+ value &= ~GITS_BASER_RO_MASK;
378
+ s->baser[index] &= GITS_BASER_RO_MASK | MAKE_64BIT_MASK(32, 32);
379
+ s->baser[index] |= value;
380
+ }
381
+ }
382
+ break;
383
+ case GITS_IIDR:
384
+ case GITS_IDREGS ... GITS_IDREGS + 0x2f:
385
+ /* RO registers, ignore the write */
386
+ qemu_log_mask(LOG_GUEST_ERROR,
387
+ "%s: invalid guest write to RO register at offset "
388
+ TARGET_FMT_plx "\n", __func__, offset);
389
+ break;
390
+ default:
391
+ result = false;
392
+ break;
393
+ }
394
return result;
48
}
395
}
49
396
50
/*
397
@@ -XXX,XX +XXX,XX @@ static bool its_readl(GICv3ITSState *s, hwaddr offset,
51
@@ -XXX,XX +XXX,XX @@ static void test_continuous_runs(void)
398
uint64_t *data, MemTxAttrs attrs)
52
}
399
{
53
400
bool result = true;
54
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
401
+ int index;
55
+ dump_buf_if_failed(buf.c, sizeof(buf));
402
403
+ switch (offset) {
404
+ case GITS_CTLR:
405
+ *data = s->ctlr;
406
+ break;
407
+ case GITS_IIDR:
408
+ *data = gicv3_iidr();
409
+ break;
410
+ case GITS_IDREGS ... GITS_IDREGS + 0x2f:
411
+ /* ID registers */
412
+ *data = gicv3_idreg(offset - GITS_IDREGS);
413
+ break;
414
+ case GITS_TYPER:
415
+ *data = extract64(s->typer, 0, 32);
416
+ break;
417
+ case GITS_TYPER + 4:
418
+ *data = extract64(s->typer, 32, 32);
419
+ break;
420
+ case GITS_CBASER:
421
+ *data = extract64(s->cbaser, 0, 32);
422
+ break;
423
+ case GITS_CBASER + 4:
424
+ *data = extract64(s->cbaser, 32, 32);
425
+ break;
426
+ case GITS_CREADR:
427
+ *data = extract64(s->creadr, 0, 32);
428
+ break;
429
+ case GITS_CREADR + 4:
430
+ *data = extract64(s->creadr, 32, 32);
431
+ break;
432
+ case GITS_CWRITER:
433
+ *data = extract64(s->cwriter, 0, 32);
434
+ break;
435
+ case GITS_CWRITER + 4:
436
+ *data = extract64(s->cwriter, 32, 32);
437
+ break;
438
+ case GITS_BASER ... GITS_BASER + 0x3f:
439
+ index = (offset - GITS_BASER) / 8;
440
+ if (offset & 7) {
441
+ *data = extract64(s->baser[index], 32, 32);
442
+ } else {
443
+ *data = extract64(s->baser[index], 0, 32);
444
+ }
445
+ break;
446
+ default:
447
+ result = false;
448
+ break;
449
+ }
450
return result;
56
}
451
}
57
452
58
/*
453
@@ -XXX,XX +XXX,XX @@ static bool its_writell(GICv3ITSState *s, hwaddr offset,
59
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_monobit(void)
454
uint64_t value, MemTxAttrs attrs)
60
}
455
{
61
456
bool result = true;
62
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
457
+ int index;
63
+ dump_buf_if_failed(buf, sizeof(buf));
458
459
+ switch (offset) {
460
+ case GITS_BASER ... GITS_BASER + 0x3f:
461
+ /*
462
+ * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
463
+ * already enabled
464
+ */
465
+ if (!(s->ctlr & ITS_CTLR_ENABLED)) {
466
+ index = (offset - GITS_BASER) / 8;
467
+ s->baser[index] &= GITS_BASER_RO_MASK;
468
+ s->baser[index] |= (value & ~GITS_BASER_RO_MASK);
469
+ }
470
+ break;
471
+ case GITS_CBASER:
472
+ /*
473
+ * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
474
+ * already enabled
475
+ */
476
+ if (!(s->ctlr & ITS_CTLR_ENABLED)) {
477
+ s->cbaser = value;
478
+ s->creadr = 0;
479
+ s->cwriter = s->creadr;
480
+ }
481
+ break;
482
+ case GITS_CWRITER:
483
+ s->cwriter = value & ~R_GITS_CWRITER_RETRY_MASK;
484
+ break;
485
+ case GITS_CREADR:
486
+ if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
487
+ s->creadr = value & ~R_GITS_CREADR_STALLED_MASK;
488
+ } else {
489
+ /* RO register, ignore the write */
490
+ qemu_log_mask(LOG_GUEST_ERROR,
491
+ "%s: invalid guest write to RO register at offset "
492
+ TARGET_FMT_plx "\n", __func__, offset);
493
+ }
494
+ break;
495
+ case GITS_TYPER:
496
+ /* RO registers, ignore the write */
497
+ qemu_log_mask(LOG_GUEST_ERROR,
498
+ "%s: invalid guest write to RO register at offset "
499
+ TARGET_FMT_plx "\n", __func__, offset);
500
+ break;
501
+ default:
502
+ result = false;
503
+ break;
504
+ }
505
return result;
64
}
506
}
65
507
66
/*
508
@@ -XXX,XX +XXX,XX @@ static bool its_readll(GICv3ITSState *s, hwaddr offset,
67
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_runs(void)
509
uint64_t *data, MemTxAttrs attrs)
68
}
510
{
69
511
bool result = true;
70
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
512
+ int index;
71
+ dump_buf_if_failed(buf.c, sizeof(buf));
513
514
+ switch (offset) {
515
+ case GITS_TYPER:
516
+ *data = s->typer;
517
+ break;
518
+ case GITS_BASER ... GITS_BASER + 0x3f:
519
+ index = (offset - GITS_BASER) / 8;
520
+ *data = s->baser[index];
521
+ break;
522
+ case GITS_CBASER:
523
+ *data = s->cbaser;
524
+ break;
525
+ case GITS_CREADR:
526
+ *data = s->creadr;
527
+ break;
528
+ case GITS_CWRITER:
529
+ *data = s->cwriter;
530
+ break;
531
+ default:
532
+ result = false;
533
+ break;
534
+ }
535
return result;
72
}
536
}
73
537
74
int main(int argc, char **argv)
538
@@ -XXX,XX +XXX,XX @@ static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
539
540
gicv3_its_init_mmio(s, &gicv3_its_control_ops, &gicv3_its_translation_ops);
541
542
+ address_space_init(&s->gicv3->dma_as, s->gicv3->dma,
543
+ "gicv3-its-sysmem");
544
+
545
/* set the ITS default features supported */
546
s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL,
547
GITS_TYPE_PHYSICAL);
548
@@ -XXX,XX +XXX,XX @@ static void gicv3_its_reset(DeviceState *dev)
549
GITS_CTE_SIZE - 1);
550
}
551
552
+static void gicv3_its_post_load(GICv3ITSState *s)
553
+{
554
+ if (s->ctlr & ITS_CTLR_ENABLED) {
555
+ extract_table_params(s);
556
+ extract_cmdq_params(s);
557
+ }
558
+}
559
+
560
static Property gicv3_its_props[] = {
561
DEFINE_PROP_LINK("parent-gicv3", GICv3ITSState, gicv3, "arm-gicv3",
562
GICv3State *),
563
@@ -XXX,XX +XXX,XX @@ static void gicv3_its_class_init(ObjectClass *klass, void *data)
564
{
565
DeviceClass *dc = DEVICE_CLASS(klass);
566
GICv3ITSClass *ic = ARM_GICV3_ITS_CLASS(klass);
567
+ GICv3ITSCommonClass *icc = ARM_GICV3_ITS_COMMON_CLASS(klass);
568
569
dc->realize = gicv3_arm_its_realize;
570
device_class_set_props(dc, gicv3_its_props);
571
device_class_set_parent_reset(dc, gicv3_its_reset, &ic->parent_reset);
572
+ icc->post_load = gicv3_its_post_load;
573
}
574
575
static const TypeInfo gicv3_its_info = {
75
--
576
--
76
2.20.1
577
2.20.1
77
578
78
579
diff view generated by jsdifflib
1
Implement the new-in-v8.1M VLDR/VSTR variants which directly
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
read or write FP system registers to memory.
3
2
3
Added functionality to trigger ITS command queue processing on
4
write to CWRITE register and process each command queue entry to
5
identify the command type and handle commands like MAPD,MAPC,SYNC.
6
7
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Eric Auger <eric.auger@redhat.com>
10
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
11
Message-id: 20210910143951.92242-4-shashi.mallela@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201119215617.29887-10-peter.maydell@linaro.org
7
---
13
---
8
target/arm/vfp.decode | 14 ++++++
14
hw/intc/gicv3_internal.h | 40 +++++
9
target/arm/translate-vfp.c.inc | 91 ++++++++++++++++++++++++++++++++++
15
hw/intc/arm_gicv3_its.c | 319 +++++++++++++++++++++++++++++++++++++++
10
2 files changed, 105 insertions(+)
16
2 files changed, 359 insertions(+)
11
17
12
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
18
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
13
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/vfp.decode
20
--- a/hw/intc/gicv3_internal.h
15
+++ b/target/arm/vfp.decode
21
+++ b/hw/intc/gicv3_internal.h
16
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR_hp ---- 1101 u:1 .0 l:1 rn:4 .... 1001 imm:8 vd=%vd_sp
22
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
17
VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp
23
#define L1TABLE_ENTRY_SIZE 8
18
VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp
24
19
25
#define GITS_CMDQ_ENTRY_SIZE 32
20
+# M-profile VLDR/VSTR to sysreg
26
+#define NUM_BYTES_IN_DW 8
21
+%vldr_sysreg 22:1 13:3
27
+
22
+%imm7_0x4 0:7 !function=times_4
28
+#define CMD_MASK 0xff
23
+
29
+
24
+&vldr_sysreg rn reg imm a w p
30
+/* ITS Commands */
25
+@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
31
+#define GITS_CMD_CLEAR 0x04
26
+ reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
32
+#define GITS_CMD_DISCARD 0x0F
27
+
33
+#define GITS_CMD_INT 0x03
28
+# P=0 W=0 is SEE "Related encodings", so split into two patterns
34
+#define GITS_CMD_MAPC 0x09
29
+VLDR_sysreg ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
35
+#define GITS_CMD_MAPD 0x08
30
+VLDR_sysreg ---- 110 0 . . 1 1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
36
+#define GITS_CMD_MAPI 0x0B
31
+VSTR_sysreg ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
37
+#define GITS_CMD_MAPTI 0x0A
32
+VSTR_sysreg ---- 110 0 . . 1 0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
38
+#define GITS_CMD_INV 0x0C
33
+
39
+#define GITS_CMD_INVALL 0x0D
34
# We split the load/store multiple up into two patterns to avoid
40
+#define GITS_CMD_SYNC 0x05
35
# overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
41
+
36
# grouping:
42
+/* MAPC command fields */
37
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
43
+#define ICID_LENGTH 16
44
+#define ICID_MASK ((1U << ICID_LENGTH) - 1)
45
+FIELD(MAPC, RDBASE, 16, 32)
46
+
47
+#define RDBASE_PROCNUM_LENGTH 16
48
+#define RDBASE_PROCNUM_MASK ((1ULL << RDBASE_PROCNUM_LENGTH) - 1)
49
+
50
+/* MAPD command fields */
51
+#define ITTADDR_LENGTH 44
52
+#define ITTADDR_SHIFT 8
53
+#define ITTADDR_MASK MAKE_64BIT_MASK(ITTADDR_SHIFT, ITTADDR_LENGTH)
54
+#define SIZE_MASK 0x1f
55
+
56
+#define DEVID_SHIFT 32
57
+#define DEVID_MASK MAKE_64BIT_MASK(32, 32)
58
+
59
+#define VALID_SHIFT 63
60
+#define CMD_FIELD_VALID_MASK (1ULL << VALID_SHIFT)
61
+#define L2_TABLE_VALID_MASK CMD_FIELD_VALID_MASK
62
+#define TABLE_ENTRY_VALID_MASK (1ULL << 0)
63
64
/**
65
* Default features advertised by this version of ITS
66
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
67
* Valid = 1 bit,ITTAddr = 44 bits,Size = 5 bits
68
*/
69
#define GITS_DTE_SIZE (0x8ULL)
70
+#define GITS_DTE_ITTADDR_SHIFT 6
71
+#define GITS_DTE_ITTADDR_MASK MAKE_64BIT_MASK(GITS_DTE_ITTADDR_SHIFT, \
72
+ ITTADDR_LENGTH)
73
74
/*
75
* 8 bytes Collection Table Entry size
76
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
38
index XXXXXXX..XXXXXXX 100644
77
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate-vfp.c.inc
78
--- a/hw/intc/arm_gicv3_its.c
40
+++ b/target/arm/translate-vfp.c.inc
79
+++ b/hw/intc/arm_gicv3_its.c
41
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
80
@@ -XXX,XX +XXX,XX @@ static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
42
return true;
81
return result;
43
}
82
}
44
83
45
+static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
84
+static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
85
+ uint64_t rdbase)
46
+{
86
+{
47
+ arg_vldr_sysreg *a = opaque;
87
+ AddressSpace *as = &s->gicv3->dma_as;
48
+ uint32_t offset = a->imm;
88
+ uint64_t value;
49
+ TCGv_i32 addr;
89
+ uint64_t l2t_addr;
50
+
90
+ bool valid_l2t;
51
+ if (!a->a) {
91
+ uint32_t l2t_id;
52
+ offset = - offset;
92
+ uint32_t max_l2_entries;
53
+ }
93
+ uint64_t cte = 0;
54
+
94
+ MemTxResult res = MEMTX_OK;
55
+ addr = load_reg(s, a->rn);
95
+
56
+ if (a->p) {
96
+ if (!s->ct.valid) {
57
+ tcg_gen_addi_i32(addr, addr, offset);
97
+ return true;
58
+ }
98
+ }
59
+
99
+
60
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
100
+ if (valid) {
61
+ gen_helper_v8m_stackcheck(cpu_env, addr);
101
+ /* add mapping entry to collection table */
62
+ }
102
+ cte = (valid & TABLE_ENTRY_VALID_MASK) | (rdbase << 1ULL);
63
+
103
+ }
64
+ gen_aa32_st_i32(s, value, addr, get_mem_index(s),
104
+
65
+ MO_UL | MO_ALIGN | s->be_data);
105
+ /*
66
+ tcg_temp_free_i32(value);
106
+ * The specification defines the format of level 1 entries of a
67
+
107
+ * 2-level table, but the format of level 2 entries and the format
68
+ if (a->w) {
108
+ * of flat-mapped tables is IMPDEF.
69
+ /* writeback */
109
+ */
70
+ if (!a->p) {
110
+ if (s->ct.indirect) {
71
+ tcg_gen_addi_i32(addr, addr, offset);
111
+ l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
72
+ }
112
+
73
+ store_reg(s, a->rn, addr);
113
+ value = address_space_ldq_le(as,
74
+ } else {
114
+ s->ct.base_addr +
75
+ tcg_temp_free_i32(addr);
115
+ (l2t_id * L1TABLE_ENTRY_SIZE),
116
+ MEMTXATTRS_UNSPECIFIED, &res);
117
+
118
+ if (res != MEMTX_OK) {
119
+ return false;
120
+ }
121
+
122
+ valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
123
+
124
+ if (valid_l2t) {
125
+ max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
126
+
127
+ l2t_addr = value & ((1ULL << 51) - 1);
128
+
129
+ address_space_stq_le(as, l2t_addr +
130
+ ((icid % max_l2_entries) * GITS_CTE_SIZE),
131
+ cte, MEMTXATTRS_UNSPECIFIED, &res);
132
+ }
133
+ } else {
134
+ /* Flat level table */
135
+ address_space_stq_le(as, s->ct.base_addr + (icid * GITS_CTE_SIZE),
136
+ cte, MEMTXATTRS_UNSPECIFIED, &res);
137
+ }
138
+ if (res != MEMTX_OK) {
139
+ return false;
140
+ } else {
141
+ return true;
76
+ }
142
+ }
77
+}
143
+}
78
+
144
+
79
+static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
145
+static bool process_mapc(GICv3ITSState *s, uint32_t offset)
80
+{
146
+{
81
+ arg_vldr_sysreg *a = opaque;
147
+ AddressSpace *as = &s->gicv3->dma_as;
82
+ uint32_t offset = a->imm;
148
+ uint16_t icid;
83
+ TCGv_i32 addr;
149
+ uint64_t rdbase;
84
+ TCGv_i32 value = tcg_temp_new_i32();
150
+ bool valid;
85
+
151
+ MemTxResult res = MEMTX_OK;
86
+ if (!a->a) {
152
+ bool result = false;
87
+ offset = - offset;
153
+ uint64_t value;
88
+ }
154
+
89
+
155
+ offset += NUM_BYTES_IN_DW;
90
+ addr = load_reg(s, a->rn);
156
+ offset += NUM_BYTES_IN_DW;
91
+ if (a->p) {
157
+
92
+ tcg_gen_addi_i32(addr, addr, offset);
158
+ value = address_space_ldq_le(as, s->cq.base_addr + offset,
93
+ }
159
+ MEMTXATTRS_UNSPECIFIED, &res);
94
+
160
+
95
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
161
+ if (res != MEMTX_OK) {
96
+ gen_helper_v8m_stackcheck(cpu_env, addr);
162
+ return result;
97
+ }
163
+ }
98
+
164
+
99
+ gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
165
+ icid = value & ICID_MASK;
100
+ MO_UL | MO_ALIGN | s->be_data);
166
+
101
+
167
+ rdbase = (value & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
102
+ if (a->w) {
168
+ rdbase &= RDBASE_PROCNUM_MASK;
103
+ /* writeback */
169
+
104
+ if (!a->p) {
170
+ valid = (value & CMD_FIELD_VALID_MASK);
105
+ tcg_gen_addi_i32(addr, addr, offset);
171
+
106
+ }
172
+ if ((icid > s->ct.maxids.max_collids) || (rdbase > s->gicv3->num_cpu)) {
107
+ store_reg(s, a->rn, addr);
173
+ qemu_log_mask(LOG_GUEST_ERROR,
108
+ } else {
174
+ "ITS MAPC: invalid collection table attributes "
109
+ tcg_temp_free_i32(addr);
175
+ "icid %d rdbase %lu\n", icid, rdbase);
110
+ }
176
+ /*
111
+ return value;
177
+ * in this implementation, in case of error
178
+ * we ignore this command and move onto the next
179
+ * command in the queue
180
+ */
181
+ } else {
182
+ result = update_cte(s, icid, valid, rdbase);
183
+ }
184
+
185
+ return result;
112
+}
186
+}
113
+
187
+
114
+static bool trans_VLDR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
188
+static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
189
+ uint8_t size, uint64_t itt_addr)
115
+{
190
+{
116
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
191
+ AddressSpace *as = &s->gicv3->dma_as;
192
+ uint64_t value;
193
+ uint64_t l2t_addr;
194
+ bool valid_l2t;
195
+ uint32_t l2t_id;
196
+ uint32_t max_l2_entries;
197
+ uint64_t dte = 0;
198
+ MemTxResult res = MEMTX_OK;
199
+
200
+ if (s->dt.valid) {
201
+ if (valid) {
202
+ /* add mapping entry to device table */
203
+ dte = (valid & TABLE_ENTRY_VALID_MASK) |
204
+ ((size & SIZE_MASK) << 1U) |
205
+ (itt_addr << GITS_DTE_ITTADDR_SHIFT);
206
+ }
207
+ } else {
208
+ return true;
209
+ }
210
+
211
+ /*
212
+ * The specification defines the format of level 1 entries of a
213
+ * 2-level table, but the format of level 2 entries and the format
214
+ * of flat-mapped tables is IMPDEF.
215
+ */
216
+ if (s->dt.indirect) {
217
+ l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE);
218
+
219
+ value = address_space_ldq_le(as,
220
+ s->dt.base_addr +
221
+ (l2t_id * L1TABLE_ENTRY_SIZE),
222
+ MEMTXATTRS_UNSPECIFIED, &res);
223
+
224
+ if (res != MEMTX_OK) {
225
+ return false;
226
+ }
227
+
228
+ valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
229
+
230
+ if (valid_l2t) {
231
+ max_l2_entries = s->dt.page_sz / s->dt.entry_sz;
232
+
233
+ l2t_addr = value & ((1ULL << 51) - 1);
234
+
235
+ address_space_stq_le(as, l2t_addr +
236
+ ((devid % max_l2_entries) * GITS_DTE_SIZE),
237
+ dte, MEMTXATTRS_UNSPECIFIED, &res);
238
+ }
239
+ } else {
240
+ /* Flat level table */
241
+ address_space_stq_le(as, s->dt.base_addr + (devid * GITS_DTE_SIZE),
242
+ dte, MEMTXATTRS_UNSPECIFIED, &res);
243
+ }
244
+ if (res != MEMTX_OK) {
117
+ return false;
245
+ return false;
118
+ }
246
+ } else {
119
+ if (a->rn == 15) {
247
+ return true;
120
+ return false;
248
+ }
121
+ }
122
+ return gen_M_fp_sysreg_write(s, a->reg, memory_to_fp_sysreg, a);
123
+}
249
+}
124
+
250
+
125
+static bool trans_VSTR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
251
+static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset)
126
+{
252
+{
127
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
253
+ AddressSpace *as = &s->gicv3->dma_as;
128
+ return false;
254
+ uint32_t devid;
129
+ }
255
+ uint8_t size;
130
+ if (a->rn == 15) {
256
+ uint64_t itt_addr;
131
+ return false;
257
+ bool valid;
132
+ }
258
+ MemTxResult res = MEMTX_OK;
133
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_memory, a);
259
+ bool result = false;
260
+
261
+ devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
262
+
263
+ offset += NUM_BYTES_IN_DW;
264
+ value = address_space_ldq_le(as, s->cq.base_addr + offset,
265
+ MEMTXATTRS_UNSPECIFIED, &res);
266
+
267
+ if (res != MEMTX_OK) {
268
+ return result;
269
+ }
270
+
271
+ size = (value & SIZE_MASK);
272
+
273
+ offset += NUM_BYTES_IN_DW;
274
+ value = address_space_ldq_le(as, s->cq.base_addr + offset,
275
+ MEMTXATTRS_UNSPECIFIED, &res);
276
+
277
+ if (res != MEMTX_OK) {
278
+ return result;
279
+ }
280
+
281
+ itt_addr = (value & ITTADDR_MASK) >> ITTADDR_SHIFT;
282
+
283
+ valid = (value & CMD_FIELD_VALID_MASK);
284
+
285
+ if ((devid > s->dt.maxids.max_devids) ||
286
+ (size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
287
+ qemu_log_mask(LOG_GUEST_ERROR,
288
+ "ITS MAPD: invalid device table attributes "
289
+ "devid %d or size %d\n", devid, size);
290
+ /*
291
+ * in this implementation, in case of error
292
+ * we ignore this command and move onto the next
293
+ * command in the queue
294
+ */
295
+ } else {
296
+ result = update_dte(s, devid, valid, size, itt_addr);
297
+ }
298
+
299
+ return result;
134
+}
300
+}
135
+
301
+
136
static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
302
+/*
137
{
303
+ * Current implementation blocks until all
138
TCGv_i32 tmp;
304
+ * commands are processed
305
+ */
306
+static void process_cmdq(GICv3ITSState *s)
307
+{
308
+ uint32_t wr_offset = 0;
309
+ uint32_t rd_offset = 0;
310
+ uint32_t cq_offset = 0;
311
+ uint64_t data;
312
+ AddressSpace *as = &s->gicv3->dma_as;
313
+ MemTxResult res = MEMTX_OK;
314
+ bool result = true;
315
+ uint8_t cmd;
316
+
317
+ if (!(s->ctlr & ITS_CTLR_ENABLED)) {
318
+ return;
319
+ }
320
+
321
+ wr_offset = FIELD_EX64(s->cwriter, GITS_CWRITER, OFFSET);
322
+
323
+ if (wr_offset > s->cq.max_entries) {
324
+ qemu_log_mask(LOG_GUEST_ERROR,
325
+ "%s: invalid write offset "
326
+ "%d\n", __func__, wr_offset);
327
+ return;
328
+ }
329
+
330
+ rd_offset = FIELD_EX64(s->creadr, GITS_CREADR, OFFSET);
331
+
332
+ if (rd_offset > s->cq.max_entries) {
333
+ qemu_log_mask(LOG_GUEST_ERROR,
334
+ "%s: invalid read offset "
335
+ "%d\n", __func__, rd_offset);
336
+ return;
337
+ }
338
+
339
+ while (wr_offset != rd_offset) {
340
+ cq_offset = (rd_offset * GITS_CMDQ_ENTRY_SIZE);
341
+ data = address_space_ldq_le(as, s->cq.base_addr + cq_offset,
342
+ MEMTXATTRS_UNSPECIFIED, &res);
343
+ if (res != MEMTX_OK) {
344
+ result = false;
345
+ }
346
+ cmd = (data & CMD_MASK);
347
+
348
+ switch (cmd) {
349
+ case GITS_CMD_INT:
350
+ break;
351
+ case GITS_CMD_CLEAR:
352
+ break;
353
+ case GITS_CMD_SYNC:
354
+ /*
355
+ * Current implementation makes a blocking synchronous call
356
+ * for every command issued earlier, hence the internal state
357
+ * is already consistent by the time SYNC command is executed.
358
+ * Hence no further processing is required for SYNC command.
359
+ */
360
+ break;
361
+ case GITS_CMD_MAPD:
362
+ result = process_mapd(s, data, cq_offset);
363
+ break;
364
+ case GITS_CMD_MAPC:
365
+ result = process_mapc(s, cq_offset);
366
+ break;
367
+ case GITS_CMD_MAPTI:
368
+ break;
369
+ case GITS_CMD_MAPI:
370
+ break;
371
+ case GITS_CMD_DISCARD:
372
+ break;
373
+ case GITS_CMD_INV:
374
+ case GITS_CMD_INVALL:
375
+ break;
376
+ default:
377
+ break;
378
+ }
379
+ if (result) {
380
+ rd_offset++;
381
+ rd_offset %= s->cq.max_entries;
382
+ s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset);
383
+ } else {
384
+ /*
385
+ * in this implementation, in case of dma read/write error
386
+ * we stall the command processing
387
+ */
388
+ s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, STALLED, 1);
389
+ qemu_log_mask(LOG_GUEST_ERROR,
390
+ "%s: %x cmd processing failed\n", __func__, cmd);
391
+ break;
392
+ }
393
+ }
394
+}
395
+
396
/*
397
* This function extracts the ITS Device and Collection table specific
398
* parameters (like base_addr, size etc) from GITS_BASER register.
399
@@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
400
extract_table_params(s);
401
extract_cmdq_params(s);
402
s->creadr = 0;
403
+ process_cmdq(s);
404
}
405
break;
406
case GITS_CBASER:
407
@@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
408
case GITS_CWRITER:
409
s->cwriter = deposit64(s->cwriter, 0, 32,
410
(value & ~R_GITS_CWRITER_RETRY_MASK));
411
+ if (s->cwriter != s->creadr) {
412
+ process_cmdq(s);
413
+ }
414
break;
415
case GITS_CWRITER + 4:
416
s->cwriter = deposit64(s->cwriter, 32, 32, value);
417
@@ -XXX,XX +XXX,XX @@ static bool its_writell(GICv3ITSState *s, hwaddr offset,
418
break;
419
case GITS_CWRITER:
420
s->cwriter = value & ~R_GITS_CWRITER_RETRY_MASK;
421
+ if (s->cwriter != s->creadr) {
422
+ process_cmdq(s);
423
+ }
424
break;
425
case GITS_CREADR:
426
if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
139
--
427
--
140
2.20.1
428
2.20.1
141
429
142
430
diff view generated by jsdifflib
1
The RAS feature has a block of memory-mapped registers at offset
1
From: Shashi Mallela <shashi.mallela@linaro.org>
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
Added ITS command queue handling for MAPTI,MAPI commands,handled ITS
7
of the "nvic-default" region is actually valid for minimal-RAS,
4
translation which triggers an LPI via INT command as well as write
8
so the main benefit of providing an explicit implementation of
5
to GITS_TRANSLATER register,defined enum to differentiate between ITS
9
the register block is more accurate LOG_UNIMP messages, and a
6
command interrupt trigger and GITS_TRANSLATER based interrupt trigger.
10
framework for where we could add a real RAS implementation later
7
Each of these commands make use of other functionalities implemented to
11
if necessary.
8
get device table entry,collection table entry or interrupt translation
9
table entry required for their processing.
12
10
11
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Message-id: 20210910143951.92242-5-shashi.mallela@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
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
---
15
---
17
include/hw/intc/armv7m_nvic.h | 1 +
16
hw/intc/gicv3_internal.h | 12 +
18
hw/intc/armv7m_nvic.c | 56 +++++++++++++++++++++++++++++++++++
17
include/hw/intc/arm_gicv3_common.h | 2 +
19
2 files changed, 57 insertions(+)
18
hw/intc/arm_gicv3_its.c | 365 ++++++++++++++++++++++++++++-
19
3 files changed, 378 insertions(+), 1 deletion(-)
20
20
21
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
21
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
22
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/intc/armv7m_nvic.h
23
--- a/hw/intc/gicv3_internal.h
24
+++ b/include/hw/intc/armv7m_nvic.h
24
+++ b/hw/intc/gicv3_internal.h
25
@@ -XXX,XX +XXX,XX @@ struct NVICState {
25
@@ -XXX,XX +XXX,XX @@ FIELD(MAPC, RDBASE, 16, 32)
26
MemoryRegion sysreg_ns_mem;
26
#define ITTADDR_MASK MAKE_64BIT_MASK(ITTADDR_SHIFT, ITTADDR_LENGTH)
27
MemoryRegion systickmem;
27
#define SIZE_MASK 0x1f
28
MemoryRegion systick_ns_mem;
28
29
+ MemoryRegion ras_mem;
29
+/* MAPI command fields */
30
MemoryRegion container;
30
+#define EVENTID_MASK ((1ULL << 32) - 1)
31
MemoryRegion defaultmem;
31
+
32
32
+/* MAPTI command fields */
33
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
33
+#define pINTID_SHIFT 32
34
+#define pINTID_MASK MAKE_64BIT_MASK(32, 32)
35
+
36
#define DEVID_SHIFT 32
37
#define DEVID_MASK MAKE_64BIT_MASK(32, 32)
38
39
@@ -XXX,XX +XXX,XX @@ FIELD(MAPC, RDBASE, 16, 32)
40
* Values: | vPEID | ICID |
41
*/
42
#define ITS_ITT_ENTRY_SIZE 0xC
43
+#define ITE_ENTRY_INTTYPE_SHIFT 1
44
+#define ITE_ENTRY_INTID_SHIFT 2
45
+#define ITE_ENTRY_INTID_MASK MAKE_64BIT_MASK(2, 24)
46
+#define ITE_ENTRY_INTSP_SHIFT 26
47
+#define ITE_ENTRY_ICID_MASK MAKE_64BIT_MASK(0, 16)
48
49
/* 16 bits EventId */
50
#define ITS_IDBITS GICD_TYPER_IDBITS
51
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
34
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/intc/armv7m_nvic.c
53
--- a/include/hw/intc/arm_gicv3_common.h
36
+++ b/hw/intc/armv7m_nvic.c
54
+++ b/include/hw/intc/arm_gicv3_common.h
37
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
55
@@ -XXX,XX +XXX,XX @@
38
.endianness = DEVICE_NATIVE_ENDIAN,
56
#define GICV3_MAXIRQ 1020
57
#define GICV3_MAXSPI (GICV3_MAXIRQ - GIC_INTERNAL)
58
59
+#define GICV3_LPI_INTID_START 8192
60
+
61
#define GICV3_REDIST_SIZE 0x20000
62
63
/* Number of SGI target-list bits */
64
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/hw/intc/arm_gicv3_its.c
67
+++ b/hw/intc/arm_gicv3_its.c
68
@@ -XXX,XX +XXX,XX @@ struct GICv3ITSClass {
69
void (*parent_reset)(DeviceState *dev);
39
};
70
};
40
71
41
+
72
+/*
42
+static MemTxResult ras_read(void *opaque, hwaddr addr,
73
+ * This is an internal enum used to distinguish between LPI triggered
43
+ uint64_t *data, unsigned size,
74
+ * via command queue and LPI triggered via gits_translater write.
44
+ MemTxAttrs attrs)
75
+ */
45
+{
76
+typedef enum ItsCmdType {
46
+ if (attrs.user) {
77
+ NONE = 0, /* internal indication for GITS_TRANSLATER write */
47
+ return MEMTX_ERROR;
78
+ CLEAR = 1,
48
+ }
79
+ DISCARD = 2,
49
+
80
+ INT = 3,
50
+ switch (addr) {
81
+} ItsCmdType;
51
+ case 0xe10: /* ERRIIDR */
82
+
52
+ /* architect field = Arm; product/variant/revision 0 */
83
+typedef struct {
53
+ *data = 0x43b;
84
+ uint32_t iteh;
54
+ break;
85
+ uint64_t itel;
55
+ case 0xfc8: /* ERRDEVID */
86
+} IteEntry;
56
+ /* Minimal RAS: we implement 0 error record indexes */
87
+
57
+ *data = 0;
88
static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
89
{
90
uint64_t result = 0;
91
@@ -XXX,XX +XXX,XX @@ static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
92
return result;
93
}
94
95
+static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
96
+ MemTxResult *res)
97
+{
98
+ AddressSpace *as = &s->gicv3->dma_as;
99
+ uint64_t l2t_addr;
100
+ uint64_t value;
101
+ bool valid_l2t;
102
+ uint32_t l2t_id;
103
+ uint32_t max_l2_entries;
104
+
105
+ if (s->ct.indirect) {
106
+ l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
107
+
108
+ value = address_space_ldq_le(as,
109
+ s->ct.base_addr +
110
+ (l2t_id * L1TABLE_ENTRY_SIZE),
111
+ MEMTXATTRS_UNSPECIFIED, res);
112
+
113
+ if (*res == MEMTX_OK) {
114
+ valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
115
+
116
+ if (valid_l2t) {
117
+ max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
118
+
119
+ l2t_addr = value & ((1ULL << 51) - 1);
120
+
121
+ *cte = address_space_ldq_le(as, l2t_addr +
122
+ ((icid % max_l2_entries) * GITS_CTE_SIZE),
123
+ MEMTXATTRS_UNSPECIFIED, res);
124
+ }
125
+ }
126
+ } else {
127
+ /* Flat level table */
128
+ *cte = address_space_ldq_le(as, s->ct.base_addr +
129
+ (icid * GITS_CTE_SIZE),
130
+ MEMTXATTRS_UNSPECIFIED, res);
131
+ }
132
+
133
+ return (*cte & TABLE_ENTRY_VALID_MASK) != 0;
134
+}
135
+
136
+static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
137
+ IteEntry ite)
138
+{
139
+ AddressSpace *as = &s->gicv3->dma_as;
140
+ uint64_t itt_addr;
141
+ MemTxResult res = MEMTX_OK;
142
+
143
+ itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT;
144
+ itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
145
+
146
+ address_space_stq_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
147
+ sizeof(uint32_t))), ite.itel, MEMTXATTRS_UNSPECIFIED,
148
+ &res);
149
+
150
+ if (res == MEMTX_OK) {
151
+ address_space_stl_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
152
+ sizeof(uint32_t))) + sizeof(uint32_t), ite.iteh,
153
+ MEMTXATTRS_UNSPECIFIED, &res);
154
+ }
155
+ if (res != MEMTX_OK) {
156
+ return false;
157
+ } else {
158
+ return true;
159
+ }
160
+}
161
+
162
+static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
163
+ uint16_t *icid, uint32_t *pIntid, MemTxResult *res)
164
+{
165
+ AddressSpace *as = &s->gicv3->dma_as;
166
+ uint64_t itt_addr;
167
+ bool status = false;
168
+ IteEntry ite = {};
169
+
170
+ itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT;
171
+ itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
172
+
173
+ ite.itel = address_space_ldq_le(as, itt_addr +
174
+ (eventid * (sizeof(uint64_t) +
175
+ sizeof(uint32_t))), MEMTXATTRS_UNSPECIFIED,
176
+ res);
177
+
178
+ if (*res == MEMTX_OK) {
179
+ ite.iteh = address_space_ldl_le(as, itt_addr +
180
+ (eventid * (sizeof(uint64_t) +
181
+ sizeof(uint32_t))) + sizeof(uint32_t),
182
+ MEMTXATTRS_UNSPECIFIED, res);
183
+
184
+ if (*res == MEMTX_OK) {
185
+ if (ite.itel & TABLE_ENTRY_VALID_MASK) {
186
+ if ((ite.itel >> ITE_ENTRY_INTTYPE_SHIFT) &
187
+ GITS_TYPE_PHYSICAL) {
188
+ *pIntid = (ite.itel & ITE_ENTRY_INTID_MASK) >>
189
+ ITE_ENTRY_INTID_SHIFT;
190
+ *icid = ite.iteh & ITE_ENTRY_ICID_MASK;
191
+ status = true;
192
+ }
193
+ }
194
+ }
195
+ }
196
+ return status;
197
+}
198
+
199
+static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
200
+{
201
+ AddressSpace *as = &s->gicv3->dma_as;
202
+ uint64_t l2t_addr;
203
+ uint64_t value;
204
+ bool valid_l2t;
205
+ uint32_t l2t_id;
206
+ uint32_t max_l2_entries;
207
+
208
+ if (s->dt.indirect) {
209
+ l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE);
210
+
211
+ value = address_space_ldq_le(as,
212
+ s->dt.base_addr +
213
+ (l2t_id * L1TABLE_ENTRY_SIZE),
214
+ MEMTXATTRS_UNSPECIFIED, res);
215
+
216
+ if (*res == MEMTX_OK) {
217
+ valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
218
+
219
+ if (valid_l2t) {
220
+ max_l2_entries = s->dt.page_sz / s->dt.entry_sz;
221
+
222
+ l2t_addr = value & ((1ULL << 51) - 1);
223
+
224
+ value = address_space_ldq_le(as, l2t_addr +
225
+ ((devid % max_l2_entries) * GITS_DTE_SIZE),
226
+ MEMTXATTRS_UNSPECIFIED, res);
227
+ }
228
+ }
229
+ } else {
230
+ /* Flat level table */
231
+ value = address_space_ldq_le(as, s->dt.base_addr +
232
+ (devid * GITS_DTE_SIZE),
233
+ MEMTXATTRS_UNSPECIFIED, res);
234
+ }
235
+
236
+ return value;
237
+}
238
+
239
+/*
240
+ * This function handles the processing of following commands based on
241
+ * the ItsCmdType parameter passed:-
242
+ * 1. triggering of lpi interrupt translation via ITS INT command
243
+ * 2. triggering of lpi interrupt translation via gits_translater register
244
+ * 3. handling of ITS CLEAR command
245
+ * 4. handling of ITS DISCARD command
246
+ */
247
+static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
248
+ ItsCmdType cmd)
249
+{
250
+ AddressSpace *as = &s->gicv3->dma_as;
251
+ uint32_t devid, eventid;
252
+ MemTxResult res = MEMTX_OK;
253
+ bool dte_valid;
254
+ uint64_t dte = 0;
255
+ uint32_t max_eventid;
256
+ uint16_t icid = 0;
257
+ uint32_t pIntid = 0;
258
+ bool ite_valid = false;
259
+ uint64_t cte = 0;
260
+ bool cte_valid = false;
261
+ bool result = false;
262
+
263
+ if (cmd == NONE) {
264
+ devid = offset;
265
+ } else {
266
+ devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
267
+
268
+ offset += NUM_BYTES_IN_DW;
269
+ value = address_space_ldq_le(as, s->cq.base_addr + offset,
270
+ MEMTXATTRS_UNSPECIFIED, &res);
271
+ }
272
+
273
+ if (res != MEMTX_OK) {
274
+ return result;
275
+ }
276
+
277
+ eventid = (value & EVENTID_MASK);
278
+
279
+ dte = get_dte(s, devid, &res);
280
+
281
+ if (res != MEMTX_OK) {
282
+ return result;
283
+ }
284
+ dte_valid = dte & TABLE_ENTRY_VALID_MASK;
285
+
286
+ if (dte_valid) {
287
+ max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1));
288
+
289
+ ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res);
290
+
291
+ if (res != MEMTX_OK) {
292
+ return result;
293
+ }
294
+
295
+ if (ite_valid) {
296
+ cte_valid = get_cte(s, icid, &cte, &res);
297
+ }
298
+
299
+ if (res != MEMTX_OK) {
300
+ return result;
301
+ }
302
+ }
303
+
304
+ if ((devid > s->dt.maxids.max_devids) || !dte_valid || !ite_valid ||
305
+ !cte_valid || (eventid > max_eventid)) {
306
+ qemu_log_mask(LOG_GUEST_ERROR,
307
+ "%s: invalid command attributes "
308
+ "devid %d or eventid %d or invalid dte %d or"
309
+ "invalid cte %d or invalid ite %d\n",
310
+ __func__, devid, eventid, dte_valid, cte_valid,
311
+ ite_valid);
312
+ /*
313
+ * in this implementation, in case of error
314
+ * we ignore this command and move onto the next
315
+ * command in the queue
316
+ */
317
+ } else {
318
+ /*
319
+ * Current implementation only supports rdbase == procnum
320
+ * Hence rdbase physical address is ignored
321
+ */
322
+ if (cmd == DISCARD) {
323
+ IteEntry ite = {};
324
+ /* remove mapping from interrupt translation table */
325
+ result = update_ite(s, eventid, dte, ite);
326
+ }
327
+ }
328
+
329
+ return result;
330
+}
331
+
332
+static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
333
+ bool ignore_pInt)
334
+{
335
+ AddressSpace *as = &s->gicv3->dma_as;
336
+ uint32_t devid, eventid;
337
+ uint32_t pIntid = 0;
338
+ uint32_t max_eventid, max_Intid;
339
+ bool dte_valid;
340
+ MemTxResult res = MEMTX_OK;
341
+ uint16_t icid = 0;
342
+ uint64_t dte = 0;
343
+ IteEntry ite;
344
+ uint32_t int_spurious = INTID_SPURIOUS;
345
+ bool result = false;
346
+
347
+ devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
348
+ offset += NUM_BYTES_IN_DW;
349
+ value = address_space_ldq_le(as, s->cq.base_addr + offset,
350
+ MEMTXATTRS_UNSPECIFIED, &res);
351
+
352
+ if (res != MEMTX_OK) {
353
+ return result;
354
+ }
355
+
356
+ eventid = (value & EVENTID_MASK);
357
+
358
+ if (!ignore_pInt) {
359
+ pIntid = ((value & pINTID_MASK) >> pINTID_SHIFT);
360
+ }
361
+
362
+ offset += NUM_BYTES_IN_DW;
363
+ value = address_space_ldq_le(as, s->cq.base_addr + offset,
364
+ MEMTXATTRS_UNSPECIFIED, &res);
365
+
366
+ if (res != MEMTX_OK) {
367
+ return result;
368
+ }
369
+
370
+ icid = value & ICID_MASK;
371
+
372
+ dte = get_dte(s, devid, &res);
373
+
374
+ if (res != MEMTX_OK) {
375
+ return result;
376
+ }
377
+ dte_valid = dte & TABLE_ENTRY_VALID_MASK;
378
+
379
+ max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1));
380
+
381
+ if (!ignore_pInt) {
382
+ max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
383
+ }
384
+
385
+ if ((devid > s->dt.maxids.max_devids) || (icid > s->ct.maxids.max_collids)
386
+ || !dte_valid || (eventid > max_eventid) ||
387
+ (!ignore_pInt && (((pIntid < GICV3_LPI_INTID_START) ||
388
+ (pIntid > max_Intid)) && (pIntid != INTID_SPURIOUS)))) {
389
+ qemu_log_mask(LOG_GUEST_ERROR,
390
+ "%s: invalid command attributes "
391
+ "devid %d or icid %d or eventid %d or pIntid %d or"
392
+ "unmapped dte %d\n", __func__, devid, icid, eventid,
393
+ pIntid, dte_valid);
394
+ /*
395
+ * in this implementation, in case of error
396
+ * we ignore this command and move onto the next
397
+ * command in the queue
398
+ */
399
+ } else {
400
+ /* add ite entry to interrupt translation table */
401
+ ite.itel = (dte_valid & TABLE_ENTRY_VALID_MASK) |
402
+ (GITS_TYPE_PHYSICAL << ITE_ENTRY_INTTYPE_SHIFT);
403
+
404
+ if (ignore_pInt) {
405
+ ite.itel |= (eventid << ITE_ENTRY_INTID_SHIFT);
406
+ } else {
407
+ ite.itel |= (pIntid << ITE_ENTRY_INTID_SHIFT);
408
+ }
409
+ ite.itel |= (int_spurious << ITE_ENTRY_INTSP_SHIFT);
410
+ ite.iteh = icid;
411
+
412
+ result = update_ite(s, eventid, dte, ite);
413
+ }
414
+
415
+ return result;
416
+}
417
+
418
static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
419
uint64_t rdbase)
420
{
421
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
422
423
switch (cmd) {
424
case GITS_CMD_INT:
425
+ res = process_its_cmd(s, data, cq_offset, INT);
426
break;
427
case GITS_CMD_CLEAR:
428
+ res = process_its_cmd(s, data, cq_offset, CLEAR);
429
break;
430
case GITS_CMD_SYNC:
431
/*
432
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
433
result = process_mapc(s, cq_offset);
434
break;
435
case GITS_CMD_MAPTI:
436
+ result = process_mapti(s, data, cq_offset, false);
437
break;
438
case GITS_CMD_MAPI:
439
+ result = process_mapti(s, data, cq_offset, true);
440
break;
441
case GITS_CMD_DISCARD:
442
+ result = process_its_cmd(s, data, cq_offset, DISCARD);
443
break;
444
case GITS_CMD_INV:
445
case GITS_CMD_INVALL:
446
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
447
uint64_t data, unsigned size,
448
MemTxAttrs attrs)
449
{
450
- return MEMTX_OK;
451
+ GICv3ITSState *s = (GICv3ITSState *)opaque;
452
+ bool result = true;
453
+ uint32_t devid = 0;
454
+
455
+ switch (offset) {
456
+ case GITS_TRANSLATER:
457
+ if (s->ctlr & ITS_CTLR_ENABLED) {
458
+ devid = attrs.requester_id;
459
+ result = process_its_cmd(s, data, devid, NONE);
460
+ }
58
+ break;
461
+ break;
59
+ default:
462
+ default:
60
+ qemu_log_mask(LOG_UNIMP, "Read RAS register offset 0x%x\n",
61
+ (uint32_t)addr);
62
+ *data = 0;
63
+ break;
463
+ break;
64
+ }
464
+ }
65
+ return MEMTX_OK;
465
+
66
+}
466
+ if (result) {
67
+
467
+ return MEMTX_OK;
68
+static MemTxResult ras_write(void *opaque, hwaddr addr,
468
+ } else {
69
+ uint64_t value, unsigned size,
70
+ MemTxAttrs attrs)
71
+{
72
+ if (attrs.user) {
73
+ return MEMTX_ERROR;
469
+ return MEMTX_ERROR;
74
+ }
470
+ }
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
}
471
}
106
472
473
static bool its_writel(GICv3ITSState *s, hwaddr offset,
107
--
474
--
108
2.20.1
475
2.20.1
109
476
110
477
diff view generated by jsdifflib
1
From: Alex Chen <alex.chen@huawei.com>
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
2
3
We should use printf format specifier "%u" instead of "%d" for
3
Added properties to enable ITS feature and define qemu system
4
argument of type "unsigned int".
4
address space memory in gicv3 common,setup distributor and
5
redistributor registers to indicate LPI support.
5
6
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
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>
9
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
10
Message-id: 20210910143951.92242-6-shashi.mallela@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
hw/misc/imx6_ccm.c | 20 ++++++++++----------
13
hw/intc/gicv3_internal.h | 2 ++
13
hw/misc/imx6_src.c | 2 +-
14
include/hw/intc/arm_gicv3_common.h | 1 +
14
2 files changed, 11 insertions(+), 11 deletions(-)
15
hw/intc/arm_gicv3_common.c | 12 ++++++++++++
16
hw/intc/arm_gicv3_dist.c | 5 ++++-
17
hw/intc/arm_gicv3_redist.c | 12 +++++++++---
18
5 files changed, 28 insertions(+), 4 deletions(-)
15
19
16
diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c
20
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/misc/imx6_ccm.c
22
--- a/hw/intc/gicv3_internal.h
19
+++ b/hw/misc/imx6_ccm.c
23
+++ b/hw/intc/gicv3_internal.h
20
@@ -XXX,XX +XXX,XX @@ static const char *imx6_ccm_reg_name(uint32_t reg)
24
@@ -XXX,XX +XXX,XX @@
21
case CCM_CMEOR:
25
#define GICD_CTLR_E1NWF (1U << 7)
22
return "CMEOR";
26
#define GICD_CTLR_RWP (1U << 31)
23
default:
27
24
- sprintf(unknown, "%d ?", reg);
28
+#define GICD_TYPER_LPIS_SHIFT 17
25
+ sprintf(unknown, "%u ?", reg);
29
+
26
return unknown;
30
/* 16 bits EventId */
31
#define GICD_TYPER_IDBITS 0xf
32
33
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/include/hw/intc/arm_gicv3_common.h
36
+++ b/include/hw/intc/arm_gicv3_common.h
37
@@ -XXX,XX +XXX,XX @@ struct GICv3State {
38
uint32_t num_cpu;
39
uint32_t num_irq;
40
uint32_t revision;
41
+ bool lpi_enable;
42
bool security_extn;
43
bool irq_reset_nonsecure;
44
bool gicd_no_migration_shift_bug;
45
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/intc/arm_gicv3_common.c
48
+++ b/hw/intc/arm_gicv3_common.c
49
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
50
return;
51
}
52
53
+ if (s->lpi_enable && !s->dma) {
54
+ error_setg(errp, "Redist-ITS: Guest 'sysmem' reference link not set");
55
+ return;
56
+ }
57
+
58
s->cpu = g_new0(GICv3CPUState, s->num_cpu);
59
60
for (i = 0; i < s->num_cpu; i++) {
61
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
62
(1 << 24) |
63
(i << 8) |
64
(last << 4);
65
+
66
+ if (s->lpi_enable) {
67
+ s->cpu[i].gicr_typer |= GICR_TYPER_PLPIS;
68
+ }
27
}
69
}
28
}
70
}
29
@@ -XXX,XX +XXX,XX @@ static const char *imx6_analog_reg_name(uint32_t reg)
71
30
case USB_ANALOG_DIGPROG:
72
@@ -XXX,XX +XXX,XX @@ static Property arm_gicv3_common_properties[] = {
31
return "USB_ANALOG_DIGPROG";
73
DEFINE_PROP_UINT32("num-cpu", GICv3State, num_cpu, 1),
32
default:
74
DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32),
33
- sprintf(unknown, "%d ?", reg);
75
DEFINE_PROP_UINT32("revision", GICv3State, revision, 3),
34
+ sprintf(unknown, "%u ?", reg);
76
+ DEFINE_PROP_BOOL("has-lpi", GICv3State, lpi_enable, 0),
35
return unknown;
77
DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0),
78
DEFINE_PROP_ARRAY("redist-region-count", GICv3State, nb_redist_regions,
79
redist_region_count, qdev_prop_uint32, uint32_t),
80
+ DEFINE_PROP_LINK("sysmem", GICv3State, dma, TYPE_MEMORY_REGION,
81
+ MemoryRegion *),
82
DEFINE_PROP_END_OF_LIST(),
83
};
84
85
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/hw/intc/arm_gicv3_dist.c
88
+++ b/hw/intc/arm_gicv3_dist.c
89
@@ -XXX,XX +XXX,XX @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
90
* A3V == 1 (non-zero values of Affinity level 3 supported)
91
* IDbits == 0xf (we support 16-bit interrupt identifiers)
92
* DVIS == 0 (Direct virtual LPI injection not supported)
93
- * LPIS == 0 (LPIs not supported)
94
+ * LPIS == 1 (LPIs are supported if affinity routing is enabled)
95
+ * num_LPIs == 0b00000 (bits [15:11],Number of LPIs as indicated
96
+ * by GICD_TYPER.IDbits)
97
* MBIS == 0 (message-based SPIs not supported)
98
* SecurityExtn == 1 if security extns supported
99
* CPUNumber == 0 since for us ARE is always 1
100
@@ -XXX,XX +XXX,XX @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
101
bool sec_extn = !(s->gicd_ctlr & GICD_CTLR_DS);
102
103
*data = (1 << 25) | (1 << 24) | (sec_extn << 10) |
104
+ (s->lpi_enable << GICD_TYPER_LPIS_SHIFT) |
105
(0xf << 19) | itlinesnumber;
106
return true;
36
}
107
}
37
}
108
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
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
109
index XXXXXXX..XXXXXXX 100644
112
--- a/hw/misc/imx6_src.c
110
--- a/hw/intc/arm_gicv3_redist.c
113
+++ b/hw/misc/imx6_src.c
111
+++ b/hw/intc/arm_gicv3_redist.c
114
@@ -XXX,XX +XXX,XX @@ static const char *imx6_src_reg_name(uint32_t reg)
112
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset,
115
case SRC_GPR10:
113
case GICR_CTLR:
116
return "SRC_GPR10";
114
/* For our implementation, GICR_TYPER.DPGS is 0 and so all
117
default:
115
* the DPG bits are RAZ/WI. We don't do anything asynchronously,
118
- sprintf(unknown, "%d ?", reg);
116
- * so UWP and RWP are RAZ/WI. And GICR_TYPER.LPIS is 0 (we don't
119
+ sprintf(unknown, "%u ?", reg);
117
- * implement LPIs) so Enable_LPIs is RES0. So there are no writable
120
return unknown;
118
- * bits for us.
121
}
119
+ * so UWP and RWP are RAZ/WI. GICR_TYPER.LPIS is 1 (we
122
}
120
+ * implement LPIs) so Enable_LPIs is programmable.
121
*/
122
+ if (cs->gicr_typer & GICR_TYPER_PLPIS) {
123
+ if (value & GICR_CTLR_ENABLE_LPIS) {
124
+ cs->gicr_ctlr |= GICR_CTLR_ENABLE_LPIS;
125
+ } else {
126
+ cs->gicr_ctlr &= ~GICR_CTLR_ENABLE_LPIS;
127
+ }
128
+ }
129
return MEMTX_OK;
130
case GICR_STATUSR:
131
/* RAZ/WI for our implementation */
123
--
132
--
124
2.20.1
133
2.20.1
125
134
126
135
diff view generated by jsdifflib
1
The constant-expander functions like negate, plus_2, etc, are
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
generally useful; move them up in translate.c so we can use them in
2
3
the VFP/Neon decoders as well as in the A32/T32/T16 decoders.
3
Implemented lpi processing at redistributor to get lpi config info
4
4
from lpi configuration table,determine priority,set pending state in
5
lpi pending table and forward the lpi to cpuif.Added logic to invoke
6
redistributor lpi processing with translated LPI which set/clear LPI
7
from ITS device as part of ITS INT,CLEAR,DISCARD command and
8
GITS_TRANSLATER processing.
9
10
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
11
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Message-id: 20210910143951.92242-7-shashi.mallela@linaro.org
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
hw/intc/gicv3_internal.h | 9 ++
10
1 file changed, 25 insertions(+), 21 deletions(-)
17
include/hw/intc/arm_gicv3_common.h | 7 ++
11
18
hw/intc/arm_gicv3.c | 14 +++
12
diff --git a/target/arm/translate.c b/target/arm/translate.c
19
hw/intc/arm_gicv3_common.c | 1 +
13
index XXXXXXX..XXXXXXX 100644
20
hw/intc/arm_gicv3_cpuif.c | 7 +-
14
--- a/target/arm/translate.c
21
hw/intc/arm_gicv3_its.c | 23 +++++
15
+++ b/target/arm/translate.c
22
hw/intc/arm_gicv3_redist.c | 141 +++++++++++++++++++++++++++++
16
@@ -XXX,XX +XXX,XX @@ static void arm_gen_condlabel(DisasContext *s)
23
7 files changed, 200 insertions(+), 2 deletions(-)
24
25
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/intc/gicv3_internal.h
28
+++ b/hw/intc/gicv3_internal.h
29
@@ -XXX,XX +XXX,XX @@ FIELD(GICR_PENDBASER, PHYADDR, 16, 36)
30
FIELD(GICR_PENDBASER, OUTERCACHE, 56, 3)
31
FIELD(GICR_PENDBASER, PTZ, 62, 1)
32
33
+#define GICR_PROPBASER_IDBITS_THRESHOLD 0xd
34
+
35
#define ICC_CTLR_EL1_CBPR (1U << 0)
36
#define ICC_CTLR_EL1_EOIMODE (1U << 1)
37
#define ICC_CTLR_EL1_PMHE (1U << 6)
38
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
39
40
#define L1TABLE_ENTRY_SIZE 8
41
42
+#define LPI_CTE_ENABLED TABLE_ENTRY_VALID_MASK
43
+#define LPI_PRIORITY_MASK 0xfc
44
+
45
#define GITS_CMDQ_ENTRY_SIZE 32
46
#define NUM_BYTES_IN_DW 8
47
48
@@ -XXX,XX +XXX,XX @@ FIELD(MAPC, RDBASE, 16, 32)
49
* Valid = 1 bit,RDBase = 36 bits(considering max RDBASE)
50
*/
51
#define GITS_CTE_SIZE (0x8ULL)
52
+#define GITS_CTE_RDBASE_PROCNUM_MASK MAKE_64BIT_MASK(1, RDBASE_PROCNUM_LENGTH)
53
54
/* Special interrupt IDs */
55
#define INTID_SECURE 1020
56
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
57
unsigned size, MemTxAttrs attrs);
58
void gicv3_dist_set_irq(GICv3State *s, int irq, int level);
59
void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level);
60
+void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level);
61
+void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level);
62
+void gicv3_redist_update_lpi(GICv3CPUState *cs);
63
void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns);
64
void gicv3_init_cpuif(GICv3State *s);
65
66
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
67
index XXXXXXX..XXXXXXX 100644
68
--- a/include/hw/intc/arm_gicv3_common.h
69
+++ b/include/hw/intc/arm_gicv3_common.h
70
@@ -XXX,XX +XXX,XX @@ struct GICv3CPUState {
71
* real state above; it doesn't need to be migrated.
72
*/
73
PendingIrq hppi;
74
+
75
+ /*
76
+ * Cached information recalculated from LPI tables
77
+ * in guest memory
78
+ */
79
+ PendingIrq hpplpi;
80
+
81
/* This is temporary working state, to avoid a malloc in gicv3_update() */
82
bool seenbetter;
83
};
84
diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/hw/intc/arm_gicv3.c
87
+++ b/hw/intc/arm_gicv3.c
88
@@ -XXX,XX +XXX,XX @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs)
89
cs->hppi.grp = gicv3_irq_group(cs->gic, cs, cs->hppi.irq);
90
}
91
92
+ if ((cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) && cs->gic->lpi_enable &&
93
+ (cs->hpplpi.prio != 0xff)) {
94
+ if (irqbetter(cs, cs->hpplpi.irq, cs->hpplpi.prio)) {
95
+ cs->hppi.irq = cs->hpplpi.irq;
96
+ cs->hppi.prio = cs->hpplpi.prio;
97
+ cs->hppi.grp = cs->hpplpi.grp;
98
+ seenbetter = true;
99
+ }
100
+ }
101
+
102
/* If the best interrupt we just found would preempt whatever
103
* was the previous best interrupt before this update, then
104
* we know it's definitely the best one now.
105
@@ -XXX,XX +XXX,XX @@ static void gicv3_set_irq(void *opaque, int irq, int level)
106
107
static void arm_gicv3_post_load(GICv3State *s)
108
{
109
+ int i;
110
/* Recalculate our cached idea of the current highest priority
111
* pending interrupt, but don't set IRQ or FIQ lines.
112
*/
113
+ for (i = 0; i < s->num_cpu; i++) {
114
+ gicv3_redist_update_lpi(&s->cpu[i]);
115
+ }
116
gicv3_full_update_noirqset(s);
117
/* Repopulate the cache of GICv3CPUState pointers for target CPUs */
118
gicv3_cache_all_target_cpustates(s);
119
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
120
index XXXXXXX..XXXXXXX 100644
121
--- a/hw/intc/arm_gicv3_common.c
122
+++ b/hw/intc/arm_gicv3_common.c
123
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_reset(DeviceState *dev)
124
memset(cs->gicr_ipriorityr, 0, sizeof(cs->gicr_ipriorityr));
125
126
cs->hppi.prio = 0xff;
127
+ cs->hpplpi.prio = 0xff;
128
129
/* State in the CPU interface must *not* be reset here, because it
130
* is part of the CPU's reset domain, not the GIC device's.
131
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/hw/intc/arm_gicv3_cpuif.c
134
+++ b/hw/intc/arm_gicv3_cpuif.c
135
@@ -XXX,XX +XXX,XX @@ static void icc_activate_irq(GICv3CPUState *cs, int irq)
136
cs->gicr_iactiver0 = deposit32(cs->gicr_iactiver0, irq, 1, 1);
137
cs->gicr_ipendr0 = deposit32(cs->gicr_ipendr0, irq, 1, 0);
138
gicv3_redist_update(cs);
139
- } else {
140
+ } else if (irq < GICV3_LPI_INTID_START) {
141
gicv3_gicd_active_set(cs->gic, irq);
142
gicv3_gicd_pending_clear(cs->gic, irq);
143
gicv3_update(cs->gic, irq, 1);
144
+ } else {
145
+ gicv3_redist_lpi_pending(cs, irq, 0);
17
}
146
}
18
}
147
}
19
148
20
+/*
149
@@ -XXX,XX +XXX,XX @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
21
+ * Constant expanders for the decoders.
150
trace_gicv3_icc_eoir_write(is_eoir0 ? 0 : 1,
22
+ */
151
gicv3_redist_affid(cs), value);
23
+
152
24
+static int negate(DisasContext *s, int x)
153
- if (irq >= cs->gic->num_irq) {
154
+ if ((irq >= cs->gic->num_irq) &&
155
+ !(cs->gic->lpi_enable && (irq >= GICV3_LPI_INTID_START))) {
156
/* This handles two cases:
157
* 1. If software writes the ID of a spurious interrupt [ie 1020-1023]
158
* to the GICC_EOIR, the GIC ignores that write.
159
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/hw/intc/arm_gicv3_its.c
162
+++ b/hw/intc/arm_gicv3_its.c
163
@@ -XXX,XX +XXX,XX @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
164
uint64_t cte = 0;
165
bool cte_valid = false;
166
bool result = false;
167
+ uint64_t rdbase;
168
169
if (cmd == NONE) {
170
devid = offset;
171
@@ -XXX,XX +XXX,XX @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
172
* Current implementation only supports rdbase == procnum
173
* Hence rdbase physical address is ignored
174
*/
175
+ rdbase = (cte & GITS_CTE_RDBASE_PROCNUM_MASK) >> 1U;
176
+
177
+ if (rdbase > s->gicv3->num_cpu) {
178
+ return result;
179
+ }
180
+
181
+ if ((cmd == CLEAR) || (cmd == DISCARD)) {
182
+ gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 0);
183
+ } else {
184
+ gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 1);
185
+ }
186
+
187
if (cmd == DISCARD) {
188
IteEntry ite = {};
189
/* remove mapping from interrupt translation table */
190
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
191
MemTxResult res = MEMTX_OK;
192
bool result = true;
193
uint8_t cmd;
194
+ int i;
195
196
if (!(s->ctlr & ITS_CTLR_ENABLED)) {
197
return;
198
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
199
break;
200
case GITS_CMD_INV:
201
case GITS_CMD_INVALL:
202
+ /*
203
+ * Current implementation doesn't cache any ITS tables,
204
+ * but the calculated lpi priority information. We only
205
+ * need to trigger lpi priority re-calculation to be in
206
+ * sync with LPI config table or pending table changes.
207
+ */
208
+ for (i = 0; i < s->gicv3->num_cpu; i++) {
209
+ gicv3_redist_update_lpi(&s->gicv3->cpu[i]);
210
+ }
211
break;
212
default:
213
break;
214
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
215
index XXXXXXX..XXXXXXX 100644
216
--- a/hw/intc/arm_gicv3_redist.c
217
+++ b/hw/intc/arm_gicv3_redist.c
218
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset,
219
if (cs->gicr_typer & GICR_TYPER_PLPIS) {
220
if (value & GICR_CTLR_ENABLE_LPIS) {
221
cs->gicr_ctlr |= GICR_CTLR_ENABLE_LPIS;
222
+ /* Check for any pending interr in pending table */
223
+ gicv3_redist_update_lpi(cs);
224
+ gicv3_redist_update(cs);
225
} else {
226
cs->gicr_ctlr &= ~GICR_CTLR_ENABLE_LPIS;
227
}
228
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
229
return r;
230
}
231
232
+static void gicv3_redist_check_lpi_priority(GICv3CPUState *cs, int irq)
25
+{
233
+{
26
+ return -x;
234
+ AddressSpace *as = &cs->gic->dma_as;
235
+ uint64_t lpict_baddr;
236
+ uint8_t lpite;
237
+ uint8_t prio;
238
+
239
+ lpict_baddr = cs->gicr_propbaser & R_GICR_PROPBASER_PHYADDR_MASK;
240
+
241
+ address_space_read(as, lpict_baddr + ((irq - GICV3_LPI_INTID_START) *
242
+ sizeof(lpite)), MEMTXATTRS_UNSPECIFIED, &lpite,
243
+ sizeof(lpite));
244
+
245
+ if (!(lpite & LPI_CTE_ENABLED)) {
246
+ return;
247
+ }
248
+
249
+ if (cs->gic->gicd_ctlr & GICD_CTLR_DS) {
250
+ prio = lpite & LPI_PRIORITY_MASK;
251
+ } else {
252
+ prio = ((lpite & LPI_PRIORITY_MASK) >> 1) | 0x80;
253
+ }
254
+
255
+ if ((prio < cs->hpplpi.prio) ||
256
+ ((prio == cs->hpplpi.prio) && (irq <= cs->hpplpi.irq))) {
257
+ cs->hpplpi.irq = irq;
258
+ cs->hpplpi.prio = prio;
259
+ /* LPIs are always non-secure Grp1 interrupts */
260
+ cs->hpplpi.grp = GICV3_G1NS;
261
+ }
27
+}
262
+}
28
+
263
+
29
+static int plus_2(DisasContext *s, int x)
264
+void gicv3_redist_update_lpi(GICv3CPUState *cs)
30
+{
265
+{
31
+ return x + 2;
266
+ /*
267
+ * This function scans the LPI pending table and for each pending
268
+ * LPI, reads the corresponding entry from LPI configuration table
269
+ * to extract the priority info and determine if the current LPI
270
+ * priority is lower than the last computed high priority lpi interrupt.
271
+ * If yes, replace current LPI as the new high priority lpi interrupt.
272
+ */
273
+ AddressSpace *as = &cs->gic->dma_as;
274
+ uint64_t lpipt_baddr;
275
+ uint32_t pendt_size = 0;
276
+ uint8_t pend;
277
+ int i, bit;
278
+ uint64_t idbits;
279
+
280
+ idbits = MIN(FIELD_EX64(cs->gicr_propbaser, GICR_PROPBASER, IDBITS),
281
+ GICD_TYPER_IDBITS);
282
+
283
+ if (!(cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || !cs->gicr_propbaser ||
284
+ !cs->gicr_pendbaser) {
285
+ return;
286
+ }
287
+
288
+ cs->hpplpi.prio = 0xff;
289
+
290
+ lpipt_baddr = cs->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK;
291
+
292
+ /* Determine the highest priority pending interrupt among LPIs */
293
+ pendt_size = (1ULL << (idbits + 1));
294
+
295
+ for (i = GICV3_LPI_INTID_START / 8; i < pendt_size / 8; i++) {
296
+ address_space_read(as, lpipt_baddr + i, MEMTXATTRS_UNSPECIFIED, &pend,
297
+ sizeof(pend));
298
+
299
+ while (pend) {
300
+ bit = ctz32(pend);
301
+ gicv3_redist_check_lpi_priority(cs, i * 8 + bit);
302
+ pend &= ~(1 << bit);
303
+ }
304
+ }
32
+}
305
+}
33
+
306
+
34
+static int times_2(DisasContext *s, int x)
307
+void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level)
35
+{
308
+{
36
+ return x * 2;
309
+ /*
310
+ * This function updates the pending bit in lpi pending table for
311
+ * the irq being activated or deactivated.
312
+ */
313
+ AddressSpace *as = &cs->gic->dma_as;
314
+ uint64_t lpipt_baddr;
315
+ bool ispend = false;
316
+ uint8_t pend;
317
+
318
+ /*
319
+ * get the bit value corresponding to this irq in the
320
+ * lpi pending table
321
+ */
322
+ lpipt_baddr = cs->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK;
323
+
324
+ address_space_read(as, lpipt_baddr + ((irq / 8) * sizeof(pend)),
325
+ MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend));
326
+
327
+ ispend = extract32(pend, irq % 8, 1);
328
+
329
+ /* no change in the value of pending bit, return */
330
+ if (ispend == level) {
331
+ return;
332
+ }
333
+ pend = deposit32(pend, irq % 8, 1, level ? 1 : 0);
334
+
335
+ address_space_write(as, lpipt_baddr + ((irq / 8) * sizeof(pend)),
336
+ MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend));
337
+
338
+ /*
339
+ * check if this LPI is better than the current hpplpi, if yes
340
+ * just set hpplpi.prio and .irq without doing a full rescan
341
+ */
342
+ if (level) {
343
+ gicv3_redist_check_lpi_priority(cs, irq);
344
+ } else {
345
+ if (irq == cs->hpplpi.irq) {
346
+ gicv3_redist_update_lpi(cs);
347
+ }
348
+ }
37
+}
349
+}
38
+
350
+
39
+static int times_4(DisasContext *s, int x)
351
+void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level)
40
+{
352
+{
41
+ return x * 4;
353
+ uint64_t idbits;
354
+
355
+ idbits = MIN(FIELD_EX64(cs->gicr_propbaser, GICR_PROPBASER, IDBITS),
356
+ GICD_TYPER_IDBITS);
357
+
358
+ if (!(cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || !cs->gicr_propbaser ||
359
+ !cs->gicr_pendbaser || (irq > (1ULL << (idbits + 1)) - 1) ||
360
+ irq < GICV3_LPI_INTID_START) {
361
+ return;
362
+ }
363
+
364
+ /* set/clear the pending bit for this irq */
365
+ gicv3_redist_lpi_pending(cs, irq, level);
366
+
367
+ gicv3_redist_update(cs);
42
+}
368
+}
43
+
369
+
44
/* Flags for the disas_set_da_iss info argument:
370
void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level)
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
{
371
{
372
/* Update redistributor state for a change in an external PPI input line */
78
--
373
--
79
2.20.1
374
2.20.1
80
375
81
376
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
2
3
The QTests perform five tests on the Xilinx ZynqMP CAN controller:
3
Added expected IORT files applicable with latest GICv3
4
Tests the CAN controller in loopback, sleep and snoop mode.
4
ITS changes.Temporarily differences in these files are
5
Tests filtering of incoming CAN messages.
5
okay.
6
6
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
8
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
8
Acked-by: Igor Mammedov <imammedo@redhat.com>
9
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 1605728926-352690-4-git-send-email-fnu.vikram@xilinx.com
10
Message-id: 20210910143951.92242-8-shashi.mallela@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
12
---
13
tests/qtest/xlnx-can-test.c | 360 ++++++++++++++++++++++++++++++++++++
13
tests/qtest/bios-tables-test-allowed-diff.h | 4 ++++
14
tests/qtest/meson.build | 1 +
14
tests/data/acpi/virt/IORT | 0
15
2 files changed, 361 insertions(+)
15
tests/data/acpi/virt/IORT.memhp | 0
16
create mode 100644 tests/qtest/xlnx-can-test.c
16
tests/data/acpi/virt/IORT.numamem | 0
17
tests/data/acpi/virt/IORT.pxb | 0
18
5 files changed, 4 insertions(+)
19
create mode 100644 tests/data/acpi/virt/IORT
20
create mode 100644 tests/data/acpi/virt/IORT.memhp
21
create mode 100644 tests/data/acpi/virt/IORT.numamem
22
create mode 100644 tests/data/acpi/virt/IORT.pxb
17
23
18
diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c
24
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/tests/qtest/bios-tables-test-allowed-diff.h
27
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
28
@@ -1 +1,5 @@
29
/* List of comma-separated changed AML files to ignore */
30
+"tests/data/acpi/virt/IORT",
31
+"tests/data/acpi/virt/IORT.memhp",
32
+"tests/data/acpi/virt/IORT.numamem",
33
+"tests/data/acpi/virt/IORT.pxb",
34
diff --git a/tests/data/acpi/virt/IORT b/tests/data/acpi/virt/IORT
19
new file mode 100644
35
new file mode 100644
20
index XXXXXXX..XXXXXXX
36
index XXXXXXX..XXXXXXX
21
--- /dev/null
37
diff --git a/tests/data/acpi/virt/IORT.memhp b/tests/data/acpi/virt/IORT.memhp
22
+++ b/tests/qtest/xlnx-can-test.c
38
new file mode 100644
23
@@ -XXX,XX +XXX,XX @@
39
index XXXXXXX..XXXXXXX
24
+/*
40
diff --git a/tests/data/acpi/virt/IORT.numamem b/tests/data/acpi/virt/IORT.numamem
25
+ * QTests for the Xilinx ZynqMP CAN controller.
41
new file mode 100644
26
+ *
42
index XXXXXXX..XXXXXXX
27
+ * Copyright (c) 2020 Xilinx Inc.
43
diff --git a/tests/data/acpi/virt/IORT.pxb b/tests/data/acpi/virt/IORT.pxb
28
+ *
44
new file mode 100644
29
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
45
index XXXXXXX..XXXXXXX
30
+ *
31
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
32
+ * of this software and associated documentation files (the "Software"), to deal
33
+ * in the Software without restriction, including without limitation the rights
34
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35
+ * copies of the Software, and to permit persons to whom the Software is
36
+ * furnished to do so, subject to the following conditions:
37
+ *
38
+ * The above copyright notice and this permission notice shall be included in
39
+ * all copies or substantial portions of the Software.
40
+ *
41
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
+ * THE SOFTWARE.
48
+ */
49
+
50
+#include "qemu/osdep.h"
51
+#include "libqos/libqtest.h"
52
+
53
+/* Base address. */
54
+#define CAN0_BASE_ADDR 0xFF060000
55
+#define CAN1_BASE_ADDR 0xFF070000
56
+
57
+/* Register addresses. */
58
+#define R_SRR_OFFSET 0x00
59
+#define R_MSR_OFFSET 0x04
60
+#define R_SR_OFFSET 0x18
61
+#define R_ISR_OFFSET 0x1C
62
+#define R_ICR_OFFSET 0x24
63
+#define R_TXID_OFFSET 0x30
64
+#define R_TXDLC_OFFSET 0x34
65
+#define R_TXDATA1_OFFSET 0x38
66
+#define R_TXDATA2_OFFSET 0x3C
67
+#define R_RXID_OFFSET 0x50
68
+#define R_RXDLC_OFFSET 0x54
69
+#define R_RXDATA1_OFFSET 0x58
70
+#define R_RXDATA2_OFFSET 0x5C
71
+#define R_AFR 0x60
72
+#define R_AFMR1 0x64
73
+#define R_AFIR1 0x68
74
+#define R_AFMR2 0x6C
75
+#define R_AFIR2 0x70
76
+#define R_AFMR3 0x74
77
+#define R_AFIR3 0x78
78
+#define R_AFMR4 0x7C
79
+#define R_AFIR4 0x80
80
+
81
+/* CAN modes. */
82
+#define CONFIG_MODE 0x00
83
+#define NORMAL_MODE 0x00
84
+#define LOOPBACK_MODE 0x02
85
+#define SNOOP_MODE 0x04
86
+#define SLEEP_MODE 0x01
87
+#define ENABLE_CAN (1 << 1)
88
+#define STATUS_NORMAL_MODE (1 << 3)
89
+#define STATUS_LOOPBACK_MODE (1 << 1)
90
+#define STATUS_SNOOP_MODE (1 << 12)
91
+#define STATUS_SLEEP_MODE (1 << 2)
92
+#define ISR_TXOK (1 << 1)
93
+#define ISR_RXOK (1 << 4)
94
+
95
+static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_rx,
96
+ uint8_t can_timestamp)
97
+{
98
+ uint16_t size = 0;
99
+ uint8_t len = 4;
100
+
101
+ while (size < len) {
102
+ if (R_RXID_OFFSET + 4 * size == R_RXDLC_OFFSET) {
103
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size] + can_timestamp);
104
+ } else {
105
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
106
+ }
107
+
108
+ size++;
109
+ }
110
+}
111
+
112
+static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx)
113
+{
114
+ uint32_t int_status;
115
+
116
+ /* Read the interrupt on CAN rx. */
117
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
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
+}
150
+
151
+/*
152
+ * This test will be transferring data from CAN0 and CAN1 through canbus. CAN0
153
+ * initiate the data transfer to can-bus, CAN1 receives the data. Test compares
154
+ * the data sent from CAN0 with received on CAN1.
155
+ */
156
+static void test_can_bus(void)
157
+{
158
+ const uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
159
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
160
+ uint32_t status = 0;
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
+
319
+ /*
320
+ * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode.
321
+ * Check the CAN0 status now. It should exit the sleep mode and receive the
322
+ * incoming data.
323
+ */
324
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
325
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
326
+
327
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
328
+
329
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
330
+
331
+ qtest_quit(qts);
332
+}
333
+
334
+/* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */
335
+static void test_can_snoopmode(void)
336
+{
337
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
338
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
339
+ uint32_t status = 0;
340
+ uint8_t can_timestamp = 1;
341
+
342
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
343
+ " -object can-bus,id=canbus0"
344
+ " -machine xlnx-zcu102.canbus0=canbus0"
345
+ " -machine xlnx-zcu102.canbus1=canbus0"
346
+ );
347
+
348
+ /* Configure the CAN0. */
349
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
350
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SNOOP_MODE);
351
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
352
+
353
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
354
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
355
+
356
+ /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */
357
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
358
+ g_assert_cmpint(status, ==, STATUS_SNOOP_MODE);
359
+
360
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
361
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
362
+
363
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
364
+
365
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
366
+
367
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
368
+
369
+ qtest_quit(qts);
370
+}
371
+
372
+int main(int argc, char **argv)
373
+{
374
+ g_test_init(&argc, &argv, NULL);
375
+
376
+ qtest_add_func("/net/can/can_bus", test_can_bus);
377
+ qtest_add_func("/net/can/can_loopback", test_can_loopback);
378
+ qtest_add_func("/net/can/can_filter", test_can_filter);
379
+ qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode);
380
+ qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode);
381
+
382
+ return g_test_run();
383
+}
384
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
385
index XXXXXXX..XXXXXXX 100644
386
--- a/tests/qtest/meson.build
387
+++ b/tests/qtest/meson.build
388
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
389
['arm-cpu-features',
390
'numa-test',
391
'boot-serial-test',
392
+ 'xlnx-can-test',
393
'migration-test']
394
395
qtests_s390x = \
396
--
46
--
397
2.20.1
47
2.20.1
398
48
399
49
diff view generated by jsdifflib
1
From: Alex Chen <alex.chen@huawei.com>
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
2
3
We should use printf format specifier "%u" instead of "%d" for
3
Included creation of ITS as part of virt platform GIC
4
argument of type "unsigned int".
4
initialization. This Emulated ITS model now co-exists with kvm
5
ITS and is enabled in absence of kvm irq kernel support in a
6
platform.
5
7
6
Reported-by: Euler Robot <euler.robot@huawei.com>
8
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Message-id: 20201126111109.112238-2-alex.chen@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20210910143951.92242-9-shashi.mallela@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
hw/misc/imx25_ccm.c | 12 ++++++------
13
include/hw/arm/virt.h | 2 ++
13
1 file changed, 6 insertions(+), 6 deletions(-)
14
target/arm/kvm_arm.h | 4 ++--
15
hw/arm/virt.c | 29 +++++++++++++++++++++++++++--
16
3 files changed, 31 insertions(+), 4 deletions(-)
14
17
15
diff --git a/hw/misc/imx25_ccm.c b/hw/misc/imx25_ccm.c
18
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/misc/imx25_ccm.c
20
--- a/include/hw/arm/virt.h
18
+++ b/hw/misc/imx25_ccm.c
21
+++ b/include/hw/arm/virt.h
19
@@ -XXX,XX +XXX,XX @@ static const char *imx25_ccm_reg_name(uint32_t reg)
22
@@ -XXX,XX +XXX,XX @@ struct VirtMachineClass {
20
case IMX25_CCM_LPIMR1_REG:
23
MachineClass parent;
21
return "lpimr1";
24
bool disallow_affinity_adjustment;
22
default:
25
bool no_its;
23
- sprintf(unknown, "[%d ?]", reg);
26
+ bool no_tcg_its;
24
+ sprintf(unknown, "[%u ?]", reg);
27
bool no_pmu;
25
return unknown;
28
bool claim_edge_triggered_timers;
29
bool smbios_old_sys_ver;
30
@@ -XXX,XX +XXX,XX @@ struct VirtMachineState {
31
bool highmem;
32
bool highmem_ecam;
33
bool its;
34
+ bool tcg_its;
35
bool virt;
36
bool ras;
37
bool mte;
38
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/kvm_arm.h
41
+++ b/target/arm/kvm_arm.h
42
@@ -XXX,XX +XXX,XX @@ static inline const char *its_class_name(void)
43
/* KVM implementation requires this capability */
44
return kvm_direct_msi_enabled() ? "arm-its-kvm" : NULL;
45
} else {
46
- /* Software emulation is not implemented yet */
47
- return NULL;
48
+ /* Software emulation based model */
49
+ return "arm-gicv3-its";
26
}
50
}
27
}
51
}
28
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mpll_clk(IMXCCMState *dev)
52
29
freq = imx_ccm_calc_pll(s->reg[IMX25_CCM_MPCTL_REG], CKIH_FREQ);
53
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/hw/arm/virt.c
56
+++ b/hw/arm/virt.c
57
@@ -XXX,XX +XXX,XX @@ static void create_its(VirtMachineState *vms)
58
const char *itsclass = its_class_name();
59
DeviceState *dev;
60
61
+ if (!strcmp(itsclass, "arm-gicv3-its")) {
62
+ if (!vms->tcg_its) {
63
+ itsclass = NULL;
64
+ }
65
+ }
66
+
67
if (!itsclass) {
68
/* Do nothing if not supported */
69
return;
70
@@ -XXX,XX +XXX,XX @@ static void create_v2m(VirtMachineState *vms)
71
vms->msi_controller = VIRT_MSI_CTRL_GICV2M;
72
}
73
74
-static void create_gic(VirtMachineState *vms)
75
+static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
76
{
77
MachineState *ms = MACHINE(vms);
78
/* We create a standalone GIC */
79
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms)
80
nb_redist_regions);
81
qdev_prop_set_uint32(vms->gic, "redist-region-count[0]", redist0_count);
82
83
+ if (!kvm_irqchip_in_kernel()) {
84
+ if (vms->tcg_its) {
85
+ object_property_set_link(OBJECT(vms->gic), "sysmem",
86
+ OBJECT(mem), &error_fatal);
87
+ qdev_prop_set_bit(vms->gic, "has-lpi", true);
88
+ }
89
+ }
90
+
91
if (nb_redist_regions == 2) {
92
uint32_t redist1_capacity =
93
vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
94
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
95
96
virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem);
97
98
- create_gic(vms);
99
+ create_gic(vms, sysmem);
100
101
virt_cpu_post_init(vms, sysmem);
102
103
@@ -XXX,XX +XXX,XX @@ static void virt_instance_init(Object *obj)
104
} else {
105
/* Default allows ITS instantiation */
106
vms->its = true;
107
+
108
+ if (vmc->no_tcg_its) {
109
+ vms->tcg_its = false;
110
+ } else {
111
+ vms->tcg_its = true;
112
+ }
30
}
113
}
31
114
32
- DPRINTF("freq = %d\n", freq);
115
/* Default disallows iommu instantiation */
33
+ DPRINTF("freq = %u\n", freq);
116
@@ -XXX,XX +XXX,XX @@ DEFINE_VIRT_MACHINE_AS_LATEST(6, 2)
34
117
35
return freq;
118
static void virt_machine_6_1_options(MachineClass *mc)
119
{
120
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
121
+
122
virt_machine_6_2_options(mc);
123
compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
124
+
125
+ /* qemu ITS was introduced with 6.2 */
126
+ vmc->no_tcg_its = true;
36
}
127
}
37
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mcu_clk(IMXCCMState *dev)
128
DEFINE_VIRT_MACHINE(6, 1)
38
129
39
freq = freq / (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], ARM_CLK_DIV));
40
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
--
130
--
74
2.20.1
131
2.20.1
75
132
76
133
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
2
3
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
3
Updated expected IORT files applicable with latest GICv3
4
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
4
ITS changes.
5
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
5
6
Message-id: 1605728926-352690-5-git-send-email-fnu.vikram@xilinx.com
6
Full diff of new file disassembly:
7
8
/*
9
* Intel ACPI Component Architecture
10
* AML/ASL+ Disassembler version 20180629 (64-bit version)
11
* Copyright (c) 2000 - 2018 Intel Corporation
12
*
13
* Disassembly of tests/data/acpi/virt/IORT.pxb, Tue Jun 29 17:35:38 2021
14
*
15
* ACPI Data Table [IORT]
16
*
17
* Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue
18
*/
19
20
[000h 0000 4] Signature : "IORT" [IO Remapping Table]
21
[004h 0004 4] Table Length : 0000007C
22
[008h 0008 1] Revision : 00
23
[009h 0009 1] Checksum : 07
24
[00Ah 0010 6] Oem ID : "BOCHS "
25
[010h 0016 8] Oem Table ID : "BXPC "
26
[018h 0024 4] Oem Revision : 00000001
27
[01Ch 0028 4] Asl Compiler ID : "BXPC"
28
[020h 0032 4] Asl Compiler Revision : 00000001
29
30
[024h 0036 4] Node Count : 00000002
31
[028h 0040 4] Node Offset : 00000030
32
[02Ch 0044 4] Reserved : 00000000
33
34
[030h 0048 1] Type : 00
35
[031h 0049 2] Length : 0018
36
[033h 0051 1] Revision : 00
37
[034h 0052 4] Reserved : 00000000
38
[038h 0056 4] Mapping Count : 00000000
39
[03Ch 0060 4] Mapping Offset : 00000000
40
41
[040h 0064 4] ItsCount : 00000001
42
[044h 0068 4] Identifiers : 00000000
43
44
[048h 0072 1] Type : 02
45
[049h 0073 2] Length : 0034
46
[04Bh 0075 1] Revision : 00
47
[04Ch 0076 4] Reserved : 00000000
48
[050h 0080 4] Mapping Count : 00000001
49
[054h 0084 4] Mapping Offset : 00000020
50
51
[058h 0088 8] Memory Properties : [IORT Memory Access Properties]
52
[058h 0088 4] Cache Coherency : 00000001
53
[05Ch 0092 1] Hints (decoded below) : 00
54
Transient : 0
55
Write Allocate : 0
56
Read Allocate : 0
57
Override : 0
58
[05Dh 0093 2] Reserved : 0000
59
[05Fh 0095 1] Memory Flags (decoded below) : 03
60
Coherency : 1
61
Device Attribute : 1
62
[060h 0096 4] ATS Attribute : 00000000
63
[064h 0100 4] PCI Segment Number : 00000000
64
[068h 0104 1] Memory Size Limit : 00
65
[069h 0105 3] Reserved : 000000
66
67
[068h 0104 4] Input base : 00000000
68
[06Ch 0108 4] ID Count : 0000FFFF
69
[070h 0112 4] Output Base : 00000000
70
[074h 0116 4] Output Reference : 00000030
71
[078h 0120 4] Flags (decoded below) : 00000000
72
Single Mapping : 0
73
74
Raw Table Data: Length 124 (0x7C)
75
76
0000: 49 4F 52 54 7C 00 00 00 00 07 42 4F 43 48 53 20 // IORT|.....BOCHS
77
0010: 42 58 50 43 20 20 20 20 01 00 00 00 42 58 50 43 // BXPC ....BXPC
78
0020: 01 00 00 00 02 00 00 00 30 00 00 00 00 00 00 00 // ........0.......
79
0030: 00 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................
80
0040: 01 00 00 00 00 00 00 00 02 34 00 00 00 00 00 00 // .........4......
81
0050: 01 00 00 00 20 00 00 00 01 00 00 00 00 00 00 03 // .... ...........
82
0060: 00 00 00 00 00 00 00 00 00 00 00 00 FF FF 00 00 // ................
83
0070: 00 00 00 00 30 00 00 00 00 00 00 00 // ....0.......
84
85
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
86
Acked-by: Igor Mammedov <imammedo@redhat.com>
87
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
88
Message-id: 20210910143951.92242-10-shashi.mallela@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
89
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
90
---
9
MAINTAINERS | 8 ++++++++
91
tests/qtest/bios-tables-test-allowed-diff.h | 4 ----
10
1 file changed, 8 insertions(+)
92
tests/data/acpi/virt/IORT | Bin 0 -> 124 bytes
93
tests/data/acpi/virt/IORT.memhp | Bin 0 -> 124 bytes
94
tests/data/acpi/virt/IORT.numamem | Bin 0 -> 124 bytes
95
tests/data/acpi/virt/IORT.pxb | Bin 0 -> 124 bytes
96
5 files changed, 4 deletions(-)
11
97
12
diff --git a/MAINTAINERS b/MAINTAINERS
98
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
13
index XXXXXXX..XXXXXXX 100644
99
index XXXXXXX..XXXXXXX 100644
14
--- a/MAINTAINERS
100
--- a/tests/qtest/bios-tables-test-allowed-diff.h
15
+++ b/MAINTAINERS
101
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
16
@@ -XXX,XX +XXX,XX @@ F: hw/net/opencores_eth.c
102
@@ -1,5 +1 @@
17
103
/* List of comma-separated changed AML files to ignore */
18
Devices
104
-"tests/data/acpi/virt/IORT",
19
-------
105
-"tests/data/acpi/virt/IORT.memhp",
20
+Xilinx CAN
106
-"tests/data/acpi/virt/IORT.numamem",
21
+M: Vikram Garhwal <fnu.vikram@xilinx.com>
107
-"tests/data/acpi/virt/IORT.pxb",
22
+M: Francisco Iglesias <francisco.iglesias@xilinx.com>
108
diff --git a/tests/data/acpi/virt/IORT b/tests/data/acpi/virt/IORT
23
+S: Maintained
109
index XXXXXXX..XXXXXXX 100644
24
+F: hw/net/can/xlnx-*
110
GIT binary patch
25
+F: include/hw/net/xlnx-*
111
literal 124
26
+F: tests/qtest/xlnx-can-test*
112
zcmebD4+^Pa00MR=e`k+i1*eDrX9XZ&1PX!JAesq?4S*O7Bw!2(4Uz`|CKCt^;wu0#
27
+
113
QRGb+i3L*dhhtM#y0PN=p0RR91
28
EDU
114
29
M: Jiri Slaby <jslaby@suse.cz>
115
literal 0
30
S: Maintained
116
HcmV?d00001
117
118
diff --git a/tests/data/acpi/virt/IORT.memhp b/tests/data/acpi/virt/IORT.memhp
119
index XXXXXXX..XXXXXXX 100644
120
GIT binary patch
121
literal 124
122
zcmebD4+^Pa00MR=e`k+i1*eDrX9XZ&1PX!JAesq?4S*O7Bw!2(4Uz`|CKCt^;wu0#
123
QRGb+i3L*dhhtM#y0PN=p0RR91
124
125
literal 0
126
HcmV?d00001
127
128
diff --git a/tests/data/acpi/virt/IORT.numamem b/tests/data/acpi/virt/IORT.numamem
129
index XXXXXXX..XXXXXXX 100644
130
GIT binary patch
131
literal 124
132
zcmebD4+^Pa00MR=e`k+i1*eDrX9XZ&1PX!JAesq?4S*O7Bw!2(4Uz`|CKCt^;wu0#
133
QRGb+i3L*dhhtM#y0PN=p0RR91
134
135
literal 0
136
HcmV?d00001
137
138
diff --git a/tests/data/acpi/virt/IORT.pxb b/tests/data/acpi/virt/IORT.pxb
139
index XXXXXXX..XXXXXXX 100644
140
GIT binary patch
141
literal 124
142
zcmebD4+^Pa00MR=e`k+i1*eDrX9XZ&1PX!JAesq?4S*O7Bw!2(4Uz`|CKCt^;wu0#
143
QRGb+i3L*dhhtM#y0PN=p0RR91
144
145
literal 0
146
HcmV?d00001
147
31
--
148
--
32
2.20.1
149
2.20.1
33
150
34
151
diff view generated by jsdifflib
1
Implement the v8.1M VSCCLRM insn, which zeros floating point
1
In v8A, the PSTATE.IL bit is set for various kinds of illegal
2
registers if there is an active floating point context.
2
exception return or mode-change attempts. We already set PSTATE.IL
3
This requires support in write_neon_element32() for the MO_32
3
(or its AArch32 equivalent CPSR.IL) in all those cases, but we
4
element size, so add it.
4
weren't implementing the part of the behaviour where attempting to
5
execute an instruction with PSTATE.IL takes an immediate exception
6
with an appropriate syndrome value.
5
7
6
Because we want to use arm_gen_condlabel(), we need to move
8
Add a new TB flags bit tracking PSTATE.IL/CPSR.IL, and generate code
7
the definition of that function up in translate.c so it is
9
to take an exception instead of whatever the instruction would have
8
before the #include of translate-vfp.c.inc.
10
been.
11
12
PSTATE.IL and CPSR.IL change only on exception entry, attempted
13
exception exit, and various AArch32 mode changes via cpsr_write().
14
These places generally already rebuild the hflags, so the only place
15
we need an extra rebuild_hflags call is in the illegal-return
16
codepath of the AArch64 exception_return helper.
9
17
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20201119215617.29887-5-peter.maydell@linaro.org
21
Message-id: 20210821195958.41312-2-richard.henderson@linaro.org
22
Message-Id: <20210817162118.24319-1-peter.maydell@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
[rth: Added missing returns; set IL bit in syndrome]
25
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
---
26
---
14
target/arm/cpu.h | 9 ++++
27
target/arm/cpu.h | 1 +
15
target/arm/m-nocp.decode | 8 +++-
28
target/arm/syndrome.h | 5 +++++
16
target/arm/translate.c | 21 +++++----
29
target/arm/translate.h | 2 ++
17
target/arm/translate-vfp.c.inc | 84 ++++++++++++++++++++++++++++++++++
30
target/arm/helper-a64.c | 1 +
18
4 files changed, 111 insertions(+), 11 deletions(-)
31
target/arm/helper.c | 8 ++++++++
32
target/arm/translate-a64.c | 11 +++++++++++
33
target/arm/translate.c | 21 +++++++++++++++++++++
34
7 files changed, 49 insertions(+)
19
35
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
36
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.h
38
--- a/target/arm/cpu.h
23
+++ b/target/arm/cpu.h
39
+++ b/target/arm/cpu.h
24
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
40
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_ANY, FPEXC_EL, 8, 2)
25
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
41
FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 10, 2)
42
/* Memory operations require alignment: SCTLR_ELx.A or CCR.UNALIGN_TRP */
43
FIELD(TBFLAG_ANY, ALIGN_MEM, 12, 1)
44
+FIELD(TBFLAG_ANY, PSTATE__IL, 13, 1)
45
46
/*
47
* Bit usage when in AArch32 state, both A- and M-profile.
48
diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/syndrome.h
51
+++ b/target/arm/syndrome.h
52
@@ -XXX,XX +XXX,XX @@ static inline uint32_t syn_wfx(int cv, int cond, int ti, bool is_16bit)
53
(cv << 24) | (cond << 20) | ti;
26
}
54
}
27
55
28
+static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id)
56
+static inline uint32_t syn_illegalstate(void)
29
+{
57
+{
30
+ /*
58
+ return (EC_ILLEGALSTATE << ARM_EL_EC_SHIFT) | ARM_EL_IL;
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
+}
59
+}
36
+
60
+
37
static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
61
#endif /* TARGET_ARM_SYNDROME_H */
38
{
62
diff --git a/target/arm/translate.h b/target/arm/translate.h
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
63
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/m-nocp.decode
64
--- a/target/arm/translate.h
43
+++ b/target/arm/m-nocp.decode
65
+++ b/target/arm/translate.h
44
@@ -XXX,XX +XXX,XX @@
66
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
45
# If the coprocessor is not present or disabled then we will generate
67
bool hstr_active;
46
# the NOCP exception; otherwise we let the insn through to the main decode.
68
/* True if memory operations require alignment */
47
69
bool align_mem;
48
+%vd_dp 22:1 12:4
70
+ /* True if PSTATE.IL is set */
49
+%vd_sp 12:4 22:1
71
+ bool pstate_il;
72
/*
73
* >= 0, a copy of PSTATE.BTYPE, which will be 0 without v8.5-BTI.
74
* < 0, set by the current instruction.
75
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/helper-a64.c
78
+++ b/target/arm/helper-a64.c
79
@@ -XXX,XX +XXX,XX @@ illegal_return:
80
if (!arm_singlestep_active(env)) {
81
env->pstate &= ~PSTATE_SS;
82
}
83
+ helper_rebuild_hflags_a64(env, cur_el);
84
qemu_log_mask(LOG_GUEST_ERROR, "Illegal exception return at EL%d: "
85
"resuming execution at 0x%" PRIx64 "\n", cur_el, env->pc);
86
}
87
diff --git a/target/arm/helper.c b/target/arm/helper.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/target/arm/helper.c
90
+++ b/target/arm/helper.c
91
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
92
DP_TBFLAG_A32(flags, HSTR_ACTIVE, 1);
93
}
94
95
+ if (env->uncached_cpsr & CPSR_IL) {
96
+ DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
97
+ }
50
+
98
+
51
&nocp cp
99
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
52
100
}
53
{
101
54
# Special cases which do not take an early NOCP: VLLDM and VLSTM
102
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
55
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
103
}
56
- # TODO: VSCCLRM (new in v8.1M) is similar:
104
}
57
- #VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
105
58
+ # VSCCLRM (new in v8.1M) is similar:
106
+ if (env->pstate & PSTATE_IL) {
59
+ VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
107
+ DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
60
+ VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
108
+ }
61
109
+
62
NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
110
if (cpu_isar_feature(aa64_mte, env_archcpu(env))) {
63
NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
111
/*
112
* Set MTE_ACTIVE if any access may be Checked, and leave clear
113
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/translate-a64.c
116
+++ b/target/arm/translate-a64.c
117
@@ -XXX,XX +XXX,XX @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
118
s->fp_access_checked = false;
119
s->sve_access_checked = false;
120
121
+ if (s->pstate_il) {
122
+ /*
123
+ * Illegal execution state. This has priority over BTI
124
+ * exceptions, but comes after instruction abort exceptions.
125
+ */
126
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
127
+ syn_illegalstate(), default_exception_el(s));
128
+ return;
129
+ }
130
+
131
if (dc_isar_feature(aa64_bti, s)) {
132
if (s->base.num_insns == 1) {
133
/*
134
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
135
#endif
136
dc->fp_excp_el = EX_TBFLAG_ANY(tb_flags, FPEXC_EL);
137
dc->align_mem = EX_TBFLAG_ANY(tb_flags, ALIGN_MEM);
138
+ dc->pstate_il = EX_TBFLAG_ANY(tb_flags, PSTATE__IL);
139
dc->sve_excp_el = EX_TBFLAG_A64(tb_flags, SVEEXC_EL);
140
dc->sve_len = (EX_TBFLAG_A64(tb_flags, ZCR_LEN) + 1) * 16;
141
dc->pauth_active = EX_TBFLAG_A64(tb_flags, PAUTH_ACTIVE);
64
diff --git a/target/arm/translate.c b/target/arm/translate.c
142
diff --git a/target/arm/translate.c b/target/arm/translate.c
65
index XXXXXXX..XXXXXXX 100644
143
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/translate.c
144
--- a/target/arm/translate.c
67
+++ b/target/arm/translate.c
145
+++ b/target/arm/translate.c
68
@@ -XXX,XX +XXX,XX @@ void arm_translate_init(void)
146
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
69
a64_translate_init();
147
return;
70
}
148
}
71
149
72
+/* Generate a label used for skipping this instruction */
150
+ if (s->pstate_il) {
73
+static void arm_gen_condlabel(DisasContext *s)
151
+ /*
74
+{
152
+ * Illegal execution state. This has priority over BTI
75
+ if (!s->condjmp) {
153
+ * exceptions, but comes after instruction abort exceptions.
76
+ s->condlabel = gen_new_label();
154
+ */
77
+ s->condjmp = 1;
155
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
78
+ }
156
+ syn_illegalstate(), default_exception_el(s));
79
+}
157
+ return;
80
+
81
/* Flags for the disas_set_da_iss info argument:
82
* lower bits hold the Rt register number, higher bits are flags.
83
*/
84
@@ -XXX,XX +XXX,XX @@ static void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop)
85
long off = neon_element_offset(reg, ele, memop);
86
87
switch (memop) {
88
+ case MO_32:
89
+ tcg_gen_st32_i64(src, cpu_env, off);
90
+ break;
91
case MO_64:
92
tcg_gen_st_i64(src, cpu_env, off);
93
break;
94
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
95
s->base.is_jmp = DISAS_UPDATE_EXIT;
96
}
97
98
-/* Generate a label used for skipping this instruction */
99
-static void arm_gen_condlabel(DisasContext *s)
100
-{
101
- if (!s->condjmp) {
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
{
110
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
111
index XXXXXXX..XXXXXXX 100644
112
--- a/target/arm/translate-vfp.c.inc
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
}
117
118
+static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
119
+{
120
+ int btmreg, topreg;
121
+ TCGv_i64 zero;
122
+ TCGv_i32 aspen, sfpa;
123
+
124
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
125
+ /* Before v8.1M, fall through in decode to NOCP check */
126
+ return false;
127
+ }
158
+ }
128
+
159
+
129
+ /* Explicitly UNDEF because this takes precedence over NOCP */
160
if (cond == 0xf) {
130
+ if (!arm_dc_feature(s, ARM_FEATURE_M_MAIN) || !s->v8m_secure) {
161
/* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
131
+ unallocated_encoding(s);
162
* choose to UNDEF. In ARMv5 and above the space is used
132
+ return true;
163
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
164
#endif
165
dc->fp_excp_el = EX_TBFLAG_ANY(tb_flags, FPEXC_EL);
166
dc->align_mem = EX_TBFLAG_ANY(tb_flags, ALIGN_MEM);
167
+ dc->pstate_il = EX_TBFLAG_ANY(tb_flags, PSTATE__IL);
168
169
if (arm_feature(env, ARM_FEATURE_M)) {
170
dc->vfp_enabled = 1;
171
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
172
}
173
dc->insn = insn;
174
175
+ if (dc->pstate_il) {
176
+ /*
177
+ * Illegal execution state. This has priority over BTI
178
+ * exceptions, but comes after instruction abort exceptions.
179
+ */
180
+ gen_exception_insn(dc, dc->pc_curr, EXCP_UDEF,
181
+ syn_illegalstate(), default_exception_el(dc));
182
+ return;
133
+ }
183
+ }
134
+
184
+
135
+ if (!dc_isar_feature(aa32_vfp_simd, s)) {
185
if (dc->eci) {
136
+ /* NOP if we have neither FP nor MVE */
186
/*
137
+ return true;
187
* For M-profile continuable instructions, ECI/ICI handling
138
+ }
139
+
140
+ /*
141
+ * If FPCCR.ASPEN != 0 && CONTROL_S.SFPA == 0 then there is no
142
+ * active floating point context so we must NOP (without doing
143
+ * any lazy state preservation or the NOCP check).
144
+ */
145
+ aspen = load_cpu_field(v7m.fpccr[M_REG_S]);
146
+ sfpa = load_cpu_field(v7m.control[M_REG_S]);
147
+ tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
148
+ tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
149
+ tcg_gen_andi_i32(sfpa, sfpa, R_V7M_CONTROL_SFPA_MASK);
150
+ tcg_gen_or_i32(sfpa, sfpa, aspen);
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
--
188
--
206
2.20.1
189
2.20.1
207
190
208
191
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The Xilinx ZynqMP CAN controller is developed based on SocketCAN, QEMU CAN bus
3
It is confusing to have different exits from translation
4
implementation. Bus connection and socketCAN connection for each CAN module
4
for various conditions in separate functions.
5
can be set through command lines.
5
6
6
Merge disas_a64_insn into its only caller. Standardize
7
Example for using single CAN:
7
on the "s" name for the DisasContext, as the code from
8
-object can-bus,id=canbus0 \
8
disas_a64_insn had more instances.
9
-machine xlnx-zcu102.canbus0=canbus0 \
9
10
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0
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>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210821195958.41312-3-richard.henderson@linaro.org
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
---
14
---
27
meson.build | 1 +
15
target/arm/translate-a64.c | 224 ++++++++++++++++++-------------------
28
hw/net/can/trace.h | 1 +
16
1 file changed, 109 insertions(+), 115 deletions(-)
29
include/hw/net/xlnx-zynqmp-can.h | 78 ++
17
30
hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++
18
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
31
hw/Kconfig | 1 +
32
hw/net/can/meson.build | 1 +
33
hw/net/can/trace-events | 9 +
34
7 files changed, 1252 insertions(+)
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
19
index XXXXXXX..XXXXXXX 100644
42
--- a/meson.build
20
--- a/target/arm/translate-a64.c
43
+++ b/meson.build
21
+++ b/target/arm/translate-a64.c
44
@@ -XXX,XX +XXX,XX @@ if have_system
22
@@ -XXX,XX +XXX,XX @@ static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
45
'hw/misc',
23
return false;
46
'hw/misc/macio',
24
}
47
'hw/net',
25
48
+ 'hw/net/can',
26
-/* C3.1 A64 instruction index by encoding */
49
'hw/nvram',
27
-static void disas_a64_insn(CPUARMState *env, DisasContext *s)
50
'hw/pci',
28
-{
51
'hw/pci-host',
29
- uint32_t insn;
52
diff --git a/hw/net/can/trace.h b/hw/net/can/trace.h
30
-
53
new file mode 100644
31
- s->pc_curr = s->base.pc_next;
54
index XXXXXXX..XXXXXXX
32
- insn = arm_ldl_code(env, s->base.pc_next, s->sctlr_b);
55
--- /dev/null
33
- s->insn = insn;
56
+++ b/hw/net/can/trace.h
34
- s->base.pc_next += 4;
57
@@ -0,0 +1 @@
35
-
58
+#include "trace/trace-hw_net_can.h"
36
- s->fp_access_checked = false;
59
diff --git a/include/hw/net/xlnx-zynqmp-can.h b/include/hw/net/xlnx-zynqmp-can.h
37
- s->sve_access_checked = false;
60
new file mode 100644
38
-
61
index XXXXXXX..XXXXXXX
39
- if (s->pstate_il) {
62
--- /dev/null
40
- /*
63
+++ b/include/hw/net/xlnx-zynqmp-can.h
41
- * Illegal execution state. This has priority over BTI
64
@@ -XXX,XX +XXX,XX @@
42
- * exceptions, but comes after instruction abort exceptions.
65
+/*
43
- */
66
+ * QEMU model of the Xilinx ZynqMP CAN controller.
44
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
67
+ *
45
- syn_illegalstate(), default_exception_el(s));
68
+ * Copyright (c) 2020 Xilinx Inc.
46
- return;
69
+ *
47
- }
70
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
48
-
71
+ *
49
- if (dc_isar_feature(aa64_bti, s)) {
72
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
50
- if (s->base.num_insns == 1) {
73
+ * Pavel Pisa.
51
- /*
74
+ *
52
- * At the first insn of the TB, compute s->guarded_page.
75
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
53
- * We delayed computing this until successfully reading
76
+ * of this software and associated documentation files (the "Software"), to deal
54
- * the first insn of the TB, above. This (mostly) ensures
77
+ * in the Software without restriction, including without limitation the rights
55
- * that the softmmu tlb entry has been populated, and the
78
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
56
- * page table GP bit is available.
79
+ * copies of the Software, and to permit persons to whom the Software is
57
- *
80
+ * furnished to do so, subject to the following conditions:
58
- * Note that we need to compute this even if btype == 0,
81
+ *
59
- * because this value is used for BR instructions later
82
+ * The above copyright notice and this permission notice shall be included in
60
- * where ENV is not available.
83
+ * all copies or substantial portions of the Software.
61
- */
84
+ *
62
- s->guarded_page = is_guarded_page(env, s);
85
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63
-
86
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64
- /* First insn can have btype set to non-zero. */
87
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
65
- tcg_debug_assert(s->btype >= 0);
88
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66
-
89
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
67
- /*
90
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
68
- * Note that the Branch Target Exception has fairly high
91
+ * THE SOFTWARE.
69
- * priority -- below debugging exceptions but above most
92
+ */
70
- * everything else. This allows us to handle this now
93
+
71
- * instead of waiting until the insn is otherwise decoded.
94
+#ifndef XLNX_ZYNQMP_CAN_H
72
- */
95
+#define XLNX_ZYNQMP_CAN_H
73
- if (s->btype != 0
96
+
74
- && s->guarded_page
97
+#include "hw/register.h"
75
- && !btype_destination_ok(insn, s->bt, s->btype)) {
98
+#include "net/can_emu.h"
76
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
99
+#include "net/can_host.h"
77
- syn_btitrap(s->btype),
100
+#include "qemu/fifo32.h"
78
- default_exception_el(s));
101
+#include "hw/ptimer.h"
79
- return;
102
+#include "hw/qdev-clock.h"
80
- }
103
+
81
- } else {
104
+#define TYPE_XLNX_ZYNQMP_CAN "xlnx.zynqmp-can"
82
- /* Not the first insn: btype must be 0. */
105
+
83
- tcg_debug_assert(s->btype == 0);
106
+#define XLNX_ZYNQMP_CAN(obj) \
84
- }
107
+ OBJECT_CHECK(XlnxZynqMPCANState, (obj), TYPE_XLNX_ZYNQMP_CAN)
85
- }
108
+
86
-
109
+#define MAX_CAN_CTRLS 2
87
- switch (extract32(insn, 25, 4)) {
110
+#define XLNX_ZYNQMP_CAN_R_MAX (0x84 / 4)
88
- case 0x0: case 0x1: case 0x3: /* UNALLOCATED */
111
+#define MAILBOX_CAPACITY 64
89
- unallocated_encoding(s);
112
+#define CAN_TIMER_MAX 0XFFFFUL
90
- break;
113
+#define CAN_DEFAULT_CLOCK (24 * 1000 * 1000)
91
- case 0x2:
114
+
92
- if (!dc_isar_feature(aa64_sve, s) || !disas_sve(s, insn)) {
115
+/* Each CAN_FRAME will have 4 * 32bit size. */
93
- unallocated_encoding(s);
116
+#define CAN_FRAME_SIZE 4
94
- }
117
+#define RXFIFO_SIZE (MAILBOX_CAPACITY * CAN_FRAME_SIZE)
95
- break;
118
+
96
- case 0x8: case 0x9: /* Data processing - immediate */
119
+typedef struct XlnxZynqMPCANState {
97
- disas_data_proc_imm(s, insn);
120
+ SysBusDevice parent_obj;
98
- break;
121
+ MemoryRegion iomem;
99
- case 0xa: case 0xb: /* Branch, exception generation and system insns */
122
+
100
- disas_b_exc_sys(s, insn);
123
+ qemu_irq irq;
101
- break;
124
+
102
- case 0x4:
125
+ CanBusClientState bus_client;
103
- case 0x6:
126
+ CanBusState *canbus;
104
- case 0xc:
127
+
105
- case 0xe: /* Loads and stores */
128
+ struct {
106
- disas_ldst(s, insn);
129
+ uint32_t ext_clk_freq;
107
- break;
130
+ } cfg;
108
- case 0x5:
131
+
109
- case 0xd: /* Data processing - register */
132
+ RegisterInfo reg_info[XLNX_ZYNQMP_CAN_R_MAX];
110
- disas_data_proc_reg(s, insn);
133
+ uint32_t regs[XLNX_ZYNQMP_CAN_R_MAX];
111
- break;
134
+
112
- case 0x7:
135
+ Fifo32 rx_fifo;
113
- case 0xf: /* Data processing - SIMD and floating point */
136
+ Fifo32 tx_fifo;
114
- disas_data_proc_simd_fp(s, insn);
137
+ Fifo32 txhpb_fifo;
115
- break;
138
+
116
- default:
139
+ ptimer_state *can_timer;
117
- assert(FALSE); /* all 15 cases should be handled above */
140
+} XlnxZynqMPCANState;
118
- break;
141
+
119
- }
142
+#endif
120
-
143
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
121
- /* if we allocated any temporaries, free them here */
144
new file mode 100644
122
- free_tmp_a64(s);
145
index XXXXXXX..XXXXXXX
123
-
146
--- /dev/null
124
- /*
147
+++ b/hw/net/can/xlnx-zynqmp-can.c
125
- * After execution of most insns, btype is reset to 0.
148
@@ -XXX,XX +XXX,XX @@
126
- * Note that we set btype == -1 when the insn sets btype.
149
+/*
127
- */
150
+ * QEMU model of the Xilinx ZynqMP CAN controller.
128
- if (s->btype > 0 && s->base.is_jmp != DISAS_NORETURN) {
151
+ * This implementation is based on the following datasheet:
129
- reset_btype(s);
152
+ * https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf
130
- }
153
+ *
131
-}
154
+ * Copyright (c) 2020 Xilinx Inc.
132
-
155
+ *
133
static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
156
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
134
CPUState *cpu)
157
+ *
135
{
158
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
136
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
159
+ * Pavel Pisa
137
160
+ *
138
static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
161
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
139
{
162
+ * of this software and associated documentation files (the "Software"), to deal
140
- DisasContext *dc = container_of(dcbase, DisasContext, base);
163
+ * in the Software without restriction, including without limitation the rights
141
+ DisasContext *s = container_of(dcbase, DisasContext, base);
164
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
142
CPUARMState *env = cpu->env_ptr;
165
+ * copies of the Software, and to permit persons to whom the Software is
143
+ uint32_t insn;
166
+ * furnished to do so, subject to the following conditions:
144
167
+ *
145
- if (dc->ss_active && !dc->pstate_ss) {
168
+ * The above copyright notice and this permission notice shall be included in
146
+ if (s->ss_active && !s->pstate_ss) {
169
+ * all copies or substantial portions of the Software.
147
/* Singlestep state is Active-pending.
170
+ *
148
* If we're in this state at the start of a TB then either
171
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
149
* a) we just took an exception to an EL which is being debugged
172
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
150
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
173
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
151
* "did not step an insn" case, and so the syndrome ISV and EX
174
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
152
* bits should be zero.
175
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
153
*/
176
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
154
- assert(dc->base.num_insns == 1);
177
+ * THE SOFTWARE.
155
- gen_swstep_exception(dc, 0, 0);
178
+ */
156
- dc->base.is_jmp = DISAS_NORETURN;
179
+
157
- } else {
180
+#include "qemu/osdep.h"
158
- disas_a64_insn(env, dc);
181
+#include "hw/sysbus.h"
159
+ assert(s->base.num_insns == 1);
182
+#include "hw/register.h"
160
+ gen_swstep_exception(s, 0, 0);
183
+#include "hw/irq.h"
161
+ s->base.is_jmp = DISAS_NORETURN;
184
+#include "qapi/error.h"
162
+ return;
185
+#include "qemu/bitops.h"
163
}
186
+#include "qemu/log.h"
164
187
+#include "qemu/cutils.h"
165
- translator_loop_temp_check(&dc->base);
188
+#include "sysemu/sysemu.h"
166
+ s->pc_curr = s->base.pc_next;
189
+#include "migration/vmstate.h"
167
+ insn = arm_ldl_code(env, s->base.pc_next, s->sctlr_b);
190
+#include "hw/qdev-properties.h"
168
+ s->insn = insn;
191
+#include "net/can_emu.h"
169
+ s->base.pc_next += 4;
192
+#include "net/can_host.h"
170
+
193
+#include "qemu/event_notifier.h"
171
+ s->fp_access_checked = false;
194
+#include "qom/object_interfaces.h"
172
+ s->sve_access_checked = false;
195
+#include "hw/net/xlnx-zynqmp-can.h"
173
+
196
+#include "trace.h"
174
+ if (s->pstate_il) {
197
+
198
+#ifndef XLNX_ZYNQMP_CAN_ERR_DEBUG
199
+#define XLNX_ZYNQMP_CAN_ERR_DEBUG 0
200
+#endif
201
+
202
+#define MAX_DLC 8
203
+#undef ERROR
204
+
205
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
206
+ FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1)
207
+ FIELD(SOFTWARE_RESET_REGISTER, SRST, 0, 1)
208
+REG32(MODE_SELECT_REGISTER, 0x4)
209
+ FIELD(MODE_SELECT_REGISTER, SNOOP, 2, 1)
210
+ FIELD(MODE_SELECT_REGISTER, LBACK, 1, 1)
211
+ FIELD(MODE_SELECT_REGISTER, SLEEP, 0, 1)
212
+REG32(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x8)
213
+ FIELD(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, BRP, 0, 8)
214
+REG32(ARBITRATION_PHASE_BIT_TIMING_REGISTER, 0xc)
215
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, SJW, 7, 2)
216
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 4, 3)
217
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 4)
218
+REG32(ERROR_COUNTER_REGISTER, 0x10)
219
+ FIELD(ERROR_COUNTER_REGISTER, REC, 8, 8)
220
+ FIELD(ERROR_COUNTER_REGISTER, TEC, 0, 8)
221
+REG32(ERROR_STATUS_REGISTER, 0x14)
222
+ FIELD(ERROR_STATUS_REGISTER, ACKER, 4, 1)
223
+ FIELD(ERROR_STATUS_REGISTER, BERR, 3, 1)
224
+ FIELD(ERROR_STATUS_REGISTER, STER, 2, 1)
225
+ FIELD(ERROR_STATUS_REGISTER, FMER, 1, 1)
226
+ FIELD(ERROR_STATUS_REGISTER, CRCER, 0, 1)
227
+REG32(STATUS_REGISTER, 0x18)
228
+ FIELD(STATUS_REGISTER, SNOOP, 12, 1)
229
+ FIELD(STATUS_REGISTER, ACFBSY, 11, 1)
230
+ FIELD(STATUS_REGISTER, TXFLL, 10, 1)
231
+ FIELD(STATUS_REGISTER, TXBFLL, 9, 1)
232
+ FIELD(STATUS_REGISTER, ESTAT, 7, 2)
233
+ FIELD(STATUS_REGISTER, ERRWRN, 6, 1)
234
+ FIELD(STATUS_REGISTER, BBSY, 5, 1)
235
+ FIELD(STATUS_REGISTER, BIDLE, 4, 1)
236
+ FIELD(STATUS_REGISTER, NORMAL, 3, 1)
237
+ FIELD(STATUS_REGISTER, SLEEP, 2, 1)
238
+ FIELD(STATUS_REGISTER, LBACK, 1, 1)
239
+ FIELD(STATUS_REGISTER, CONFIG, 0, 1)
240
+REG32(INTERRUPT_STATUS_REGISTER, 0x1c)
241
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFEMP, 14, 1)
242
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFWMEMP, 13, 1)
243
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL, 12, 1)
244
+ FIELD(INTERRUPT_STATUS_REGISTER, WKUP, 11, 1)
245
+ FIELD(INTERRUPT_STATUS_REGISTER, SLP, 10, 1)
246
+ FIELD(INTERRUPT_STATUS_REGISTER, BSOFF, 9, 1)
247
+ FIELD(INTERRUPT_STATUS_REGISTER, ERROR, 8, 1)
248
+ FIELD(INTERRUPT_STATUS_REGISTER, RXNEMP, 7, 1)
249
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOFLW, 6, 1)
250
+ FIELD(INTERRUPT_STATUS_REGISTER, RXUFLW, 5, 1)
251
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1)
252
+ FIELD(INTERRUPT_STATUS_REGISTER, TXBFLL, 3, 1)
253
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFLL, 2, 1)
254
+ FIELD(INTERRUPT_STATUS_REGISTER, TXOK, 1, 1)
255
+ FIELD(INTERRUPT_STATUS_REGISTER, ARBLST, 0, 1)
256
+REG32(INTERRUPT_ENABLE_REGISTER, 0x20)
257
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFEMP, 14, 1)
258
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFWMEMP, 13, 1)
259
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL, 12, 1)
260
+ FIELD(INTERRUPT_ENABLE_REGISTER, EWKUP, 11, 1)
261
+ FIELD(INTERRUPT_ENABLE_REGISTER, ESLP, 10, 1)
262
+ FIELD(INTERRUPT_ENABLE_REGISTER, EBSOFF, 9, 1)
263
+ FIELD(INTERRUPT_ENABLE_REGISTER, EERROR, 8, 1)
264
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXNEMP, 7, 1)
265
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOFLW, 6, 1)
266
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXUFLW, 5, 1)
267
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1)
268
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXBFLL, 3, 1)
269
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFLL, 2, 1)
270
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1)
271
+ FIELD(INTERRUPT_ENABLE_REGISTER, EARBLST, 0, 1)
272
+REG32(INTERRUPT_CLEAR_REGISTER, 0x24)
273
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFEMP, 14, 1)
274
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFWMEMP, 13, 1)
275
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL, 12, 1)
276
+ FIELD(INTERRUPT_CLEAR_REGISTER, CWKUP, 11, 1)
277
+ FIELD(INTERRUPT_CLEAR_REGISTER, CSLP, 10, 1)
278
+ FIELD(INTERRUPT_CLEAR_REGISTER, CBSOFF, 9, 1)
279
+ FIELD(INTERRUPT_CLEAR_REGISTER, CERROR, 8, 1)
280
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXNEMP, 7, 1)
281
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOFLW, 6, 1)
282
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXUFLW, 5, 1)
283
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1)
284
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXBFLL, 3, 1)
285
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFLL, 2, 1)
286
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1)
287
+ FIELD(INTERRUPT_CLEAR_REGISTER, CARBLST, 0, 1)
288
+REG32(TIMESTAMP_REGISTER, 0x28)
289
+ FIELD(TIMESTAMP_REGISTER, CTS, 0, 1)
290
+REG32(WIR, 0x2c)
291
+ FIELD(WIR, EW, 8, 8)
292
+ FIELD(WIR, FW, 0, 8)
293
+REG32(TXFIFO_ID, 0x30)
294
+ FIELD(TXFIFO_ID, IDH, 21, 11)
295
+ FIELD(TXFIFO_ID, SRRRTR, 20, 1)
296
+ FIELD(TXFIFO_ID, IDE, 19, 1)
297
+ FIELD(TXFIFO_ID, IDL, 1, 18)
298
+ FIELD(TXFIFO_ID, RTR, 0, 1)
299
+REG32(TXFIFO_DLC, 0x34)
300
+ FIELD(TXFIFO_DLC, DLC, 28, 4)
301
+REG32(TXFIFO_DATA1, 0x38)
302
+ FIELD(TXFIFO_DATA1, DB0, 24, 8)
303
+ FIELD(TXFIFO_DATA1, DB1, 16, 8)
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
+ }
411
+
412
+ if ((fifo32_num_used(&s->rx_fifo) / CAN_FRAME_SIZE) >
413
+ ARRAY_FIELD_EX32(s->regs, WIR, FW)) {
414
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL, 1);
415
+ }
416
+
417
+ /* RX Interrupts. */
418
+ if (fifo32_num_used(&s->rx_fifo) >= CAN_FRAME_SIZE) {
419
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXNEMP, 1);
420
+ }
421
+
422
+ /* TX interrupts. */
423
+ if (fifo32_is_empty(&s->tx_fifo)) {
424
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFEMP, 1);
425
+ }
426
+
427
+ if (fifo32_is_full(&s->tx_fifo)) {
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
+ /*
175
+ /*
520
+ * If all bits are zero then XlnxZynqMPCAN is set in normal mode.
176
+ * Illegal execution state. This has priority over BTI
177
+ * exceptions, but comes after instruction abort exceptions.
521
+ */
178
+ */
522
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 1);
179
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
523
+ /* Set wakeup interrupt bit. */
180
+ syn_illegalstate(), default_exception_el(s));
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;
181
+ return;
600
+ }
182
+ }
601
+
183
+
602
+ while (!fifo32_is_empty(fifo)) {
184
+ if (dc_isar_feature(aa64_bti, s)) {
603
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
185
+ if (s->base.num_insns == 1) {
604
+ data[i] = fifo32_pop(fifo);
605
+ }
606
+
607
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
608
+ /*
186
+ /*
609
+ * Controller is in loopback. In Loopback mode, the CAN core
187
+ * At the first insn of the TB, compute s->guarded_page.
610
+ * transmits a recessive bitstream on to the XlnxZynqMPCAN Bus.
188
+ * We delayed computing this until successfully reading
611
+ * Any message transmitted is looped back to the RX line and
189
+ * the first insn of the TB, above. This (mostly) ensures
612
+ * acknowledged. The XlnxZynqMPCAN core receives any message
190
+ * that the softmmu tlb entry has been populated, and the
613
+ * that it transmits.
191
+ * page table GP bit is available.
192
+ *
193
+ * Note that we need to compute this even if btype == 0,
194
+ * because this value is used for BR instructions later
195
+ * where ENV is not available.
614
+ */
196
+ */
615
+ if (fifo32_is_full(&s->rx_fifo)) {
197
+ s->guarded_page = is_guarded_page(env, s);
616
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
198
+
617
+ } else {
199
+ /* First insn can have btype set to non-zero. */
618
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
200
+ tcg_debug_assert(s->btype >= 0);
619
+ fifo32_push(&s->rx_fifo, data[i]);
201
+
620
+ }
202
+ /*
621
+
203
+ * Note that the Branch Target Exception has fairly high
622
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
204
+ * priority -- below debugging exceptions but above most
205
+ * everything else. This allows us to handle this now
206
+ * instead of waiting until the insn is otherwise decoded.
207
+ */
208
+ if (s->btype != 0
209
+ && s->guarded_page
210
+ && !btype_destination_ok(insn, s->bt, s->btype)) {
211
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
212
+ syn_btitrap(s->btype),
213
+ default_exception_el(s));
214
+ return;
623
+ }
215
+ }
624
+ } else {
216
+ } else {
625
+ /* Normal mode Tx. */
217
+ /* Not the first insn: btype must be 0. */
626
+ generate_frame(&frame, data);
218
+ tcg_debug_assert(s->btype == 0);
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
+ }
219
+ }
635
+ }
220
+ }
636
+
221
+
637
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1);
222
+ switch (extract32(insn, 25, 4)) {
638
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, TXBFLL, 0);
223
+ case 0x0: case 0x1: case 0x3: /* UNALLOCATED */
639
+
224
+ unallocated_encoding(s);
640
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) {
225
+ break;
641
+ can_exit_sleep_mode(s);
226
+ case 0x2:
642
+ }
227
+ if (!dc_isar_feature(aa64_sve, s) || !disas_sve(s, insn)) {
643
+
228
+ unallocated_encoding(s);
644
+ can_update_irq(s);
229
+ }
645
+}
230
+ break;
646
+
231
+ case 0x8: case 0x9: /* Data processing - immediate */
647
+static uint64_t can_srr_pre_write(RegisterInfo *reg, uint64_t val)
232
+ disas_data_proc_imm(s, insn);
648
+{
233
+ break;
649
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
234
+ case 0xa: case 0xb: /* Branch, exception generation and system insns */
650
+
235
+ disas_b_exc_sys(s, insn);
651
+ ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN,
236
+ break;
652
+ FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN));
237
+ case 0x4:
653
+
238
+ case 0x6:
654
+ if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) {
239
+ case 0xc:
655
+ trace_xlnx_can_reset(val);
240
+ case 0xe: /* Loads and stores */
656
+
241
+ disas_ldst(s, insn);
657
+ /* First, core will do software reset then will enter in config mode. */
242
+ break;
658
+ can_config_reset(s);
243
+ case 0x5:
659
+ }
244
+ case 0xd: /* Data processing - register */
660
+
245
+ disas_data_proc_reg(s, insn);
661
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
246
+ break;
662
+ can_config_mode(s);
247
+ case 0x7:
663
+ } else {
248
+ case 0xf: /* Data processing - SIMD and floating point */
664
+ /*
249
+ disas_data_proc_simd_fp(s, insn);
665
+ * Leave config mode. Now XlnxZynqMPCAN core will enter normal,
250
+ break;
666
+ * sleep, snoop or loopback mode depending upon LBACK, SLEEP, SNOOP
251
+ default:
667
+ * register states.
252
+ assert(FALSE); /* all 15 cases should be handled above */
668
+ */
253
+ break;
669
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0);
254
+ }
670
+
255
+
671
+ ptimer_transaction_begin(s->can_timer);
256
+ /* if we allocated any temporaries, free them here */
672
+ ptimer_set_count(s->can_timer, 0);
257
+ free_tmp_a64(s);
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
+
258
+
690
+ /*
259
+ /*
691
+ * Multiple mode set check. This is done to make sure user doesn't set
260
+ * After execution of most insns, btype is reset to 0.
692
+ * multiple modes.
261
+ * Note that we set btype == -1 when the insn sets btype.
693
+ */
262
+ */
694
+ multi_mode = FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK) +
263
+ if (s->btype > 0 && s->base.is_jmp != DISAS_NORETURN) {
695
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP) +
264
+ reset_btype(s);
696
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP);
265
+ }
697
+
266
+
698
+ if (multi_mode > 1) {
267
+ translator_loop_temp_check(&s->base);
699
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
268
}
700
+
269
701
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to config"
270
static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
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,
1091
+ .write = register_write_memory,
1092
+ .endianness = DEVICE_LITTLE_ENDIAN,
1093
+ .valid = {
1094
+ .min_access_size = 4,
1095
+ .max_access_size = 4,
1096
+ },
1097
+};
1098
+
1099
+static void xlnx_zynqmp_can_reset_init(Object *obj, ResetType type)
1100
+{
1101
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1102
+ unsigned int i;
1103
+
1104
+ for (i = R_RXFIFO_ID; i < ARRAY_SIZE(s->reg_info); ++i) {
1105
+ register_reset(&s->reg_info[i]);
1106
+ }
1107
+
1108
+ ptimer_transaction_begin(s->can_timer);
1109
+ ptimer_set_count(s->can_timer, 0);
1110
+ ptimer_transaction_commit(s->can_timer);
1111
+}
1112
+
1113
+static void xlnx_zynqmp_can_reset_hold(Object *obj)
1114
+{
1115
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1116
+ unsigned int i;
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);
1245
+
1246
+ RegisterInfoArray *reg_array;
1247
+
1248
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_CAN,
1249
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1250
+ reg_array = register_init_block32(DEVICE(obj), can_regs_info,
1251
+ ARRAY_SIZE(can_regs_info),
1252
+ s->reg_info, s->regs,
1253
+ &can_ops,
1254
+ XLNX_ZYNQMP_CAN_ERR_DEBUG,
1255
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1256
+
1257
+ memory_region_add_subregion(&s->iomem, 0x00, &reg_array->mem);
1258
+ sysbus_init_mmio(sbd, &s->iomem);
1259
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
1260
+}
1261
+
1262
+static const VMStateDescription vmstate_can = {
1263
+ .name = TYPE_XLNX_ZYNQMP_CAN,
1264
+ .version_id = 1,
1265
+ .minimum_version_id = 1,
1266
+ .fields = (VMStateField[]) {
1267
+ VMSTATE_FIFO32(rx_fifo, XlnxZynqMPCANState),
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(),
1273
+ }
1274
+};
1275
+
1276
+static Property xlnx_zynqmp_can_properties[] = {
1277
+ DEFINE_PROP_UINT32("ext_clk_freq", XlnxZynqMPCANState, cfg.ext_clk_freq,
1278
+ CAN_DEFAULT_CLOCK),
1279
+ DEFINE_PROP_LINK("canbus", XlnxZynqMPCANState, canbus, TYPE_CAN_BUS,
1280
+ CanBusState *),
1281
+ DEFINE_PROP_END_OF_LIST(),
1282
+};
1283
+
1284
+static void xlnx_zynqmp_can_class_init(ObjectClass *klass, void *data)
1285
+{
1286
+ DeviceClass *dc = DEVICE_CLASS(klass);
1287
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
1288
+
1289
+ rc->phases.enter = xlnx_zynqmp_can_reset_init;
1290
+ rc->phases.hold = xlnx_zynqmp_can_reset_hold;
1291
+ dc->realize = xlnx_zynqmp_can_realize;
1292
+ device_class_set_props(dc, xlnx_zynqmp_can_properties);
1293
+ dc->vmsd = &vmstate_can;
1294
+}
1295
+
1296
+static const TypeInfo can_info = {
1297
+ .name = TYPE_XLNX_ZYNQMP_CAN,
1298
+ .parent = TYPE_SYS_BUS_DEVICE,
1299
+ .instance_size = sizeof(XlnxZynqMPCANState),
1300
+ .class_init = xlnx_zynqmp_can_class_init,
1301
+ .instance_init = xlnx_zynqmp_can_init,
1302
+};
1303
+
1304
+static void can_register_types(void)
1305
+{
1306
+ type_register_static(&can_info);
1307
+}
1308
+
1309
+type_init(can_register_types)
1310
diff --git a/hw/Kconfig b/hw/Kconfig
1311
index XXXXXXX..XXXXXXX 100644
1312
--- a/hw/Kconfig
1313
+++ b/hw/Kconfig
1314
@@ -XXX,XX +XXX,XX @@ config XILINX_AXI
1315
config XLNX_ZYNQMP
1316
bool
1317
select REGISTER
1318
+ select CAN_BUS
1319
diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
1320
index XXXXXXX..XXXXXXX 100644
1321
--- a/hw/net/can/meson.build
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
--
271
--
1344
2.20.1
272
2.20.1
1345
273
1346
274
diff view generated by jsdifflib
Deleted patch
1
From: Alex Chen <alex.chen@huawei.com>
2
1
3
We should use printf format specifier "%u" instead of "%d" for
4
argument of type "unsigned int".
5
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Message-id: 20201126111109.112238-5-alex.chen@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/misc/imx6ul_ccm.c | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/hw/misc/imx6ul_ccm.c b/hw/misc/imx6ul_ccm.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/misc/imx6ul_ccm.c
18
+++ b/hw/misc/imx6ul_ccm.c
19
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_ccm_reg_name(uint32_t reg)
20
case CCM_CMEOR:
21
return "CMEOR";
22
default:
23
- sprintf(unknown, "%d ?", reg);
24
+ sprintf(unknown, "%u ?", reg);
25
return unknown;
26
}
27
}
28
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_analog_reg_name(uint32_t reg)
29
case USB_ANALOG_DIGPROG:
30
return "USB_ANALOG_DIGPROG";
31
default:
32
- sprintf(unknown, "%d ?", reg);
33
+ sprintf(unknown, "%u ?", reg);
34
return unknown;
35
}
36
}
37
--
38
2.20.1
39
40
diff view generated by jsdifflib
Deleted patch
1
In v8.1M the PXN architecture extension adds a new PXN bit to the
2
MPU_RLAR registers, which forbids execution of code in the region
3
from a privileged mode.
4
1
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
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20201119215617.29887-3-peter.maydell@linaro.org
11
---
12
target/arm/helper.c | 7 ++++++-
13
1 file changed, 6 insertions(+), 1 deletion(-)
14
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
18
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
20
} else {
21
uint32_t ap = extract32(env->pmsav8.rbar[secure][matchregion], 1, 2);
22
uint32_t xn = extract32(env->pmsav8.rbar[secure][matchregion], 0, 1);
23
+ bool pxn = false;
24
+
25
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
26
+ pxn = extract32(env->pmsav8.rlar[secure][matchregion], 4, 1);
27
+ }
28
29
if (m_is_system_region(env, address)) {
30
/* System space is always execute never */
31
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
32
}
33
34
*prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
35
- if (*prot && !xn) {
36
+ if (*prot && !xn && !(pxn && !is_user)) {
37
*prot |= PAGE_EXEC;
38
}
39
/* We don't need to look the attribute up in the MAIR0/MAIR1
40
--
41
2.20.1
42
43
diff view generated by jsdifflib
Deleted patch
1
In arm_cpu_realizefn() we check whether the board code disabled EL3
2
via the has_el3 CPU object property, which we create if the CPU
3
starts with the ARM_FEATURE_EL3 feature bit. If it is disabled, then
4
we turn off ARM_FEATURE_EL3 and also zero out the relevant fields in
5
the ID_PFR1 and ID_AA64PFR0 registers.
6
1
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
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20201119215617.29887-4-peter.maydell@linaro.org
17
---
18
target/arm/cpu.c | 2 +-
19
1 file changed, 1 insertion(+), 1 deletion(-)
20
21
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.c
24
+++ b/target/arm/cpu.c
25
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
26
}
27
}
28
29
- if (!cpu->has_el3) {
30
+ if (!arm_feature(env, ARM_FEATURE_M) && !cpu->has_el3) {
31
/* If the has_el3 CPU property is disabled then we need to disable the
32
* feature.
33
*/
34
--
35
2.20.1
36
37
diff view generated by jsdifflib
1
Factor out the code which handles M-profile lazy FP state preservation
1
By default, QEMU will allow devices to be plugged into a bus up to
2
from full_vfp_access_check(); accesses to the FPCXT_NS register are
2
the bus class's device count limit. If the user creates a device on
3
a special case which need to do just this part (corresponding in the
3
the command line or via the monitor and doesn't explicitly specify
4
pseudocode to the PreserveFPState() function), and not the full
4
the bus to plug it in, QEMU will plug it into the first non-full bus
5
set of actions matching the pseudocode ExecuteFPCheck() which
5
that it finds.
6
normal FP instructions need to do.
6
7
This is fine in most cases, but some machines have multiple buses of
8
a given type, some of which are dedicated to on-board devices and
9
some of which have an externally exposed connector for user-pluggable
10
devices. One example is I2C buses.
11
12
Provide a new function qbus_mark_full() so that a machine model can
13
mark this kind of "internal only" bus as 'full' after it has created
14
all the devices that should be plugged into that bus. The "find a
15
non-full bus" algorithm will then skip the internal-only bus when
16
looking for a place to plug in user-created devices.
7
17
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Message-id: 20210903151435.22379-2-peter.maydell@linaro.org
11
Message-id: 20201119215617.29887-13-peter.maydell@linaro.org
12
---
21
---
13
target/arm/translate-vfp.c.inc | 45 ++++++++++++++++++++--------------
22
include/hw/qdev-core.h | 24 ++++++++++++++++++++++++
14
1 file changed, 27 insertions(+), 18 deletions(-)
23
softmmu/qdev-monitor.c | 7 ++++++-
24
2 files changed, 30 insertions(+), 1 deletion(-)
15
25
16
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
26
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
17
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate-vfp.c.inc
28
--- a/include/hw/qdev-core.h
19
+++ b/target/arm/translate-vfp.c.inc
29
+++ b/include/hw/qdev-core.h
20
@@ -XXX,XX +XXX,XX @@ static inline long vfp_f16_offset(unsigned reg, bool top)
30
@@ -XXX,XX +XXX,XX @@ struct BusState {
21
return offs;
31
HotplugHandler *hotplug_handler;
32
int max_index;
33
bool realized;
34
+ bool full;
35
int num_children;
36
37
/*
38
@@ -XXX,XX +XXX,XX @@ static inline bool qbus_is_hotpluggable(BusState *bus)
39
return bus->hotplug_handler;
22
}
40
}
23
41
24
+/*
42
+/**
25
+ * Generate code for M-profile lazy FP state preservation if needed;
43
+ * qbus_mark_full: Mark this bus as full, so no more devices can be attached
26
+ * this corresponds to the pseudocode PreserveFPState() function.
44
+ * @bus: Bus to mark as full
45
+ *
46
+ * By default, QEMU will allow devices to be plugged into a bus up
47
+ * to the bus class's device count limit. Calling this function
48
+ * marks a particular bus as full, so that no more devices can be
49
+ * plugged into it. In particular this means that the bus will not
50
+ * be considered as a candidate for plugging in devices created by
51
+ * the user on the commandline or via the monitor.
52
+ * If a machine has multiple buses of a given type, such as I2C,
53
+ * where some of those buses in the real hardware are used only for
54
+ * internal devices and some are exposed via expansion ports, you
55
+ * can use this function to mark the internal-only buses as full
56
+ * after you have created all their internal devices. Then user
57
+ * created devices will appear on the expansion-port bus where
58
+ * guest software expects them.
27
+ */
59
+ */
28
+static void gen_preserve_fp_state(DisasContext *s)
60
+static inline void qbus_mark_full(BusState *bus)
29
+{
61
+{
30
+ if (s->v7m_lspact) {
62
+ bus->full = true;
31
+ /*
32
+ * Lazy state saving affects external memory and also the NVIC,
33
+ * so we must mark it as an IO operation for icount (and cause
34
+ * this to be the last insn in the TB).
35
+ */
36
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
37
+ s->base.is_jmp = DISAS_UPDATE_EXIT;
38
+ gen_io_start();
39
+ }
40
+ gen_helper_v7m_preserve_fp_state(cpu_env);
41
+ /*
42
+ * If the preserve_fp_state helper doesn't throw an exception
43
+ * then it will clear LSPACT; we don't need to repeat this for
44
+ * any further FP insns in this TB.
45
+ */
46
+ s->v7m_lspact = false;
47
+ }
48
+}
63
+}
49
+
64
+
50
/*
65
void device_listener_register(DeviceListener *listener);
51
* Check that VFP access is enabled. If it is, do the necessary
66
void device_listener_unregister(DeviceListener *listener);
52
* M-profile lazy-FP handling and then return true.
67
53
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
68
diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
54
/* Handle M-profile lazy FP state mechanics */
69
index XXXXXXX..XXXXXXX 100644
55
70
--- a/softmmu/qdev-monitor.c
56
/* Trigger lazy-state preservation if necessary */
71
+++ b/softmmu/qdev-monitor.c
57
- if (s->v7m_lspact) {
72
@@ -XXX,XX +XXX,XX @@ static DeviceState *qbus_find_dev(BusState *bus, char *elem)
58
- /*
73
59
- * Lazy state saving affects external memory and also the NVIC,
74
static inline bool qbus_is_full(BusState *bus)
60
- * so we must mark it as an IO operation for icount (and cause
75
{
61
- * this to be the last insn in the TB).
76
- BusClass *bus_class = BUS_GET_CLASS(bus);
62
- */
77
+ BusClass *bus_class;
63
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
78
+
64
- s->base.is_jmp = DISAS_UPDATE_EXIT;
79
+ if (bus->full) {
65
- gen_io_start();
80
+ return true;
66
- }
81
+ }
67
- gen_helper_v7m_preserve_fp_state(cpu_env);
82
+ bus_class = BUS_GET_CLASS(bus);
68
- /*
83
return bus_class->max_dev && bus->num_children >= bus_class->max_dev;
69
- * If the preserve_fp_state helper doesn't throw an exception
84
}
70
- * then it will clear LSPACT; we don't need to repeat this for
85
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
--
86
--
80
2.20.1
87
2.20.1
81
88
82
89
diff view generated by jsdifflib
1
v8.1M introduces a new TRD flag in the CCR register, which enables
1
The mps2-tz boards use a data-driven structure to create the devices
2
checking for stack frame integrity signatures on SG instructions.
2
that sit behind peripheral protection controllers. Currently the
3
Add the code in the SG insn implementation for the new behaviour.
3
functions which create these devices are passed an 'opaque' pointer
4
which is always the address within the machine struct of the device
5
to create, and some "all devices need this" information like irqs and
6
addresses.
7
8
If a specific device needs more information than this, it is
9
currently not possible to pass that through from the PPCInfo
10
data structure. Add support for passing an extra data parameter,
11
so that we can more flexibly handle the needs of specific
12
device types. To provide some type-safety we make this extra
13
parameter a pointer to a union (which initially has no members).
14
15
In particular, we would like to be able to indicate which of the
16
i2c controllers are for on-board devices only and which are
17
connected to the external 'shield' expansion port; a subsequent
18
patch will use this mechanism for that purpose.
4
19
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-24-peter.maydell@linaro.org
22
Message-id: 20210903151435.22379-3-peter.maydell@linaro.org
8
---
23
---
9
target/arm/m_helper.c | 86 +++++++++++++++++++++++++++++++++++++++++++
24
hw/arm/mps2-tz.c | 35 ++++++++++++++++++++++-------------
10
1 file changed, 86 insertions(+)
25
1 file changed, 22 insertions(+), 13 deletions(-)
11
26
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
27
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
13
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/m_helper.c
29
--- a/hw/arm/mps2-tz.c
15
+++ b/target/arm/m_helper.c
30
+++ b/hw/arm/mps2-tz.c
16
@@ -XXX,XX +XXX,XX @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx,
31
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
17
return true;
32
}
18
}
33
}
19
34
20
+static bool v7m_read_sg_stack_word(ARMCPU *cpu, ARMMMUIdx mmu_idx,
35
+/* Union describing the device-specific extra data we pass to the devfn. */
21
+ uint32_t addr, uint32_t *spdata)
36
+typedef union PPCExtraData {
22
+{
37
+} PPCExtraData;
23
+ /*
24
+ * Read a word of data from the stack for the SG instruction,
25
+ * writing the value into *spdata. If the load succeeds, return
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
+
38
+
42
+ if (get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &physaddr,
39
/* Most of the devices in the AN505 FPGA image sit behind
43
+ &attrs, &prot, &page_size, &fi, &cacheattrs)) {
40
* Peripheral Protection Controllers. These data structures
44
+ /* MPU/SAU lookup failed */
41
* define the layout of which devices sit behind which PPCs.
45
+ if (fi.type == ARMFault_QEMU_SFault) {
42
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
46
+ qemu_log_mask(CPU_LOG_INT,
43
*/
47
+ "...SecureFault during stack word read\n");
44
typedef MemoryRegion *MakeDevFn(MPS2TZMachineState *mms, void *opaque,
48
+ env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK | R_V7M_SFSR_SFARVALID_MASK;
45
const char *name, hwaddr size,
49
+ env->v7m.sfar = addr;
46
- const int *irqs);
50
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
47
+ const int *irqs,
51
+ } else {
48
+ const PPCExtraData *extradata);
52
+ qemu_log_mask(CPU_LOG_INT,
49
53
+ "...MemManageFault during stack word read\n");
50
typedef struct PPCPortInfo {
54
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_DACCVIOL_MASK |
51
const char *name;
55
+ R_V7M_CFSR_MMARVALID_MASK;
52
@@ -XXX,XX +XXX,XX @@ typedef struct PPCPortInfo {
56
+ env->v7m.mmfar[M_REG_S] = addr;
53
hwaddr addr;
57
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM, false);
54
hwaddr size;
58
+ }
55
int irqs[3]; /* currently no device needs more IRQ lines than this */
59
+ return false;
56
+ PPCExtraData extradata; /* to pass device-specific info to the devfn */
60
+ }
57
} PPCPortInfo;
61
+ value = address_space_ldl(arm_addressspace(cs, attrs), physaddr,
58
62
+ attrs, &txres);
59
typedef struct PPCInfo {
63
+ if (txres != MEMTX_OK) {
60
@@ -XXX,XX +XXX,XX @@ typedef struct PPCInfo {
64
+ /* BusFault trying to read the data */
61
static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
65
+ qemu_log_mask(CPU_LOG_INT,
62
void *opaque,
66
+ "...BusFault during stack word read\n");
63
const char *name, hwaddr size,
67
+ env->v7m.cfsr[M_REG_NS] |=
64
- const int *irqs)
68
+ (R_V7M_CFSR_PRECISERR_MASK | R_V7M_CFSR_BFARVALID_MASK);
65
+ const int *irqs,
69
+ env->v7m.bfar = addr;
66
+ const PPCExtraData *extradata)
70
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_BUS, false);
67
{
71
+ return false;
68
/* Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
72
+ }
69
* and return a pointer to its MemoryRegion.
73
+
70
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
74
+ *spdata = value;
71
75
+ return true;
72
static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
76
+}
73
const char *name, hwaddr size,
77
+
74
- const int *irqs)
78
static bool v7m_handle_execute_nsc(ARMCPU *cpu)
75
+ const int *irqs, const PPCExtraData *extradata)
76
{
77
/* The irq[] array is tx, rx, combined, in that order */
78
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
79
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
80
81
static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
82
const char *name, hwaddr size,
83
- const int *irqs)
84
+ const int *irqs, const PPCExtraData *extradata)
85
{
86
MPS2SCC *scc = opaque;
87
DeviceState *sccdev;
88
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
89
90
static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
91
const char *name, hwaddr size,
92
- const int *irqs)
93
+ const int *irqs, const PPCExtraData *extradata)
94
{
95
MPS2FPGAIO *fpgaio = opaque;
96
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
97
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
98
99
static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
100
const char *name, hwaddr size,
101
- const int *irqs)
102
+ const int *irqs,
103
+ const PPCExtraData *extradata)
104
{
105
SysBusDevice *s;
106
NICInfo *nd = &nd_table[0];
107
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
108
109
static MemoryRegion *make_eth_usb(MPS2TZMachineState *mms, void *opaque,
110
const char *name, hwaddr size,
111
- const int *irqs)
112
+ const int *irqs,
113
+ const PPCExtraData *extradata)
79
{
114
{
80
/*
115
/*
81
@@ -XXX,XX +XXX,XX @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu)
116
* The AN524 makes the ethernet and USB share a PPC port.
82
*/
117
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_usb(MPS2TZMachineState *mms, void *opaque,
83
qemu_log_mask(CPU_LOG_INT, "...really an SG instruction at 0x%08" PRIx32
118
84
", executing it\n", env->regs[15]);
119
static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
85
+
120
const char *name, hwaddr size,
86
+ if (cpu_isar_feature(aa32_m_sec_state, cpu) &&
121
- const int *irqs)
87
+ !arm_v7m_is_handler_mode(env)) {
122
+ const int *irqs, const PPCExtraData *extradata)
88
+ /*
123
{
89
+ * v8.1M exception stack frame integrity check. Note that we
124
TZMPC *mpc = opaque;
90
+ * must perform the memory access even if CCR_S.TRD is zero
125
int i = mpc - &mms->mpc[0];
91
+ * and we aren't going to check what the data loaded is.
126
@@ -XXX,XX +XXX,XX @@ static void remap_irq_fn(void *opaque, int n, int level)
92
+ */
127
93
+ uint32_t spdata, sp;
128
static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
94
+
129
const char *name, hwaddr size,
95
+ /*
130
- const int *irqs)
96
+ * We know we are currently NS, so the S stack pointers must be
131
+ const int *irqs, const PPCExtraData *extradata)
97
+ * in other_ss_{psp,msp}, not in regs[13]/other_sp.
132
{
98
+ */
133
/* The irq[] array is DMACINTR, DMACINTERR, DMACINTTC, in that order */
99
+ sp = v7m_using_psp(env) ? env->v7m.other_ss_psp : env->v7m.other_ss_msp;
134
PL080State *dma = opaque;
100
+ if (!v7m_read_sg_stack_word(cpu, mmu_idx, sp, &spdata)) {
135
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
101
+ /* Stack access failed and an exception has been pended */
136
102
+ return false;
137
static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
103
+ }
138
const char *name, hwaddr size,
104
+
139
- const int *irqs)
105
+ if (env->v7m.ccr[M_REG_S] & R_V7M_CCR_TRD_MASK) {
140
+ const int *irqs, const PPCExtraData *extradata)
106
+ if (((spdata & ~1) == 0xfefa125a) ||
141
{
107
+ !(env->v7m.control[M_REG_S] & 1)) {
142
/*
108
+ goto gen_invep;
143
* The AN505 has five PL022 SPI controllers.
109
+ }
144
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
110
+ }
145
111
+ }
146
static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
112
+
147
const char *name, hwaddr size,
113
env->regs[14] &= ~1;
148
- const int *irqs)
114
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
149
+ const int *irqs, const PPCExtraData *extradata)
115
switch_v7m_security_state(env, true);
150
{
151
ArmSbconI2CState *i2c = opaque;
152
SysBusDevice *s;
153
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
154
155
static MemoryRegion *make_rtc(MPS2TZMachineState *mms, void *opaque,
156
const char *name, hwaddr size,
157
- const int *irqs)
158
+ const int *irqs, const PPCExtraData *extradata)
159
{
160
PL031State *pl031 = opaque;
161
SysBusDevice *s;
162
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
163
}
164
165
mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size,
166
- pinfo->irqs);
167
+ pinfo->irqs, &pinfo->extradata);
168
portname = g_strdup_printf("port[%d]", port);
169
object_property_set_link(OBJECT(ppc), portname, OBJECT(mr),
170
&error_fatal);
116
--
171
--
117
2.20.1
172
2.20.1
118
173
119
174
diff view generated by jsdifflib
1
In v8.1M the new CLRM instruction allows zeroing an arbitrary set of
1
The various MPS2 boards have multiple I2C buses: typically a bus
2
the general-purpose registers and APSR. Implement this.
2
dedicated to the audio configuration, one for the LCD touchscreen
3
3
controller, one for a DDR4 EEPROM, and two which are connected to the
4
The encoding is a subset of the LDMIA T2 encoding, using what would
4
external Shield expansion connector. Mark the buses which are used
5
be Rn=0b1111 (which UNDEFs for LDMIA).
5
only for board-internal devices as 'full' so that if the user creates
6
i2c devices on the commandline without specifying a bus name then
7
they will be connected to the I2C controller used for the Shield
8
connector, where guest software will expect them.
6
9
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20201119215617.29887-6-peter.maydell@linaro.org
12
Message-id: 20210903151435.22379-4-peter.maydell@linaro.org
10
---
13
---
11
target/arm/t32.decode | 6 +++++-
14
hw/arm/mps2-tz.c | 57 ++++++++++++++++++++++++++++++++++++------------
12
target/arm/translate.c | 38 ++++++++++++++++++++++++++++++++++++++
15
1 file changed, 43 insertions(+), 14 deletions(-)
13
2 files changed, 43 insertions(+), 1 deletion(-)
14
16
15
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/t32.decode
19
--- a/hw/arm/mps2-tz.c
18
+++ b/target/arm/t32.decode
20
+++ b/hw/arm/mps2-tz.c
19
@@ -XXX,XX +XXX,XX @@ UXTAB 1111 1010 0101 .... 1111 .... 10.. .... @rrr_rot
21
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
20
22
21
STM_t32 1110 1000 10.0 .... ................ @ldstm i=1 b=0
23
/* Union describing the device-specific extra data we pass to the devfn. */
22
STM_t32 1110 1001 00.0 .... ................ @ldstm i=0 b=1
24
typedef union PPCExtraData {
23
-LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
25
+ bool i2c_internal;
24
+{
26
} PPCExtraData;
25
+ # Rn=15 UNDEFs for LDM; M-profile CLRM uses that encoding
27
26
+ CLRM 1110 1000 1001 1111 list:16
28
/* Most of the devices in the AN505 FPGA image sit behind
27
+ LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
29
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
28
+}
30
object_initialize_child(OBJECT(mms), name, i2c, TYPE_ARM_SBCON_I2C);
29
LDM_t32 1110 1001 00.1 .... ................ @ldstm i=0 b=1
31
s = SYS_BUS_DEVICE(i2c);
30
32
sysbus_realize(s, &error_fatal);
31
&rfe !extern rn w pu
32
diff --git a/target/arm/translate.c b/target/arm/translate.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/translate.c
35
+++ b/target/arm/translate.c
36
@@ -XXX,XX +XXX,XX @@ static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
37
return do_ldm(s, a, 1);
38
}
39
40
+static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
41
+{
42
+ int i;
43
+ TCGv_i32 zero;
44
+
33
+
45
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
34
+ /*
46
+ return false;
35
+ * If this is an internal-use-only i2c bus, mark it full
36
+ * so that user-created i2c devices are not plugged into it.
37
+ * If we implement models of any on-board i2c devices that
38
+ * plug in to one of the internal-use-only buses, then we will
39
+ * need to create and plugging those in here before we mark the
40
+ * bus as full.
41
+ */
42
+ if (extradata->i2c_internal) {
43
+ BusState *qbus = qdev_get_child_bus(DEVICE(i2c), "i2c");
44
+ qbus_mark_full(qbus);
47
+ }
45
+ }
48
+
46
+
49
+ if (extract32(a->list, 13, 1)) {
47
return sysbus_mmio_get_region(s, 0);
50
+ return false;
48
}
51
+ }
49
52
+
50
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
53
+ if (!a->list) {
51
{ "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000, { 36, 37, 44 } },
54
+ /* UNPREDICTABLE; we choose to UNDEF */
52
{ "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000, { 38, 39, 45 } },
55
+ return false;
53
{ "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000, { 40, 41, 46 } },
56
+ }
54
- { "i2c0", make_i2c, &mms->i2c[0], 0x40207000, 0x1000 },
57
+
55
- { "i2c1", make_i2c, &mms->i2c[1], 0x40208000, 0x1000 },
58
+ zero = tcg_const_i32(0);
56
- { "i2c2", make_i2c, &mms->i2c[2], 0x4020c000, 0x1000 },
59
+ for (i = 0; i < 15; i++) {
57
- { "i2c3", make_i2c, &mms->i2c[3], 0x4020d000, 0x1000 },
60
+ if (extract32(a->list, i, 1)) {
58
+ { "i2c0", make_i2c, &mms->i2c[0], 0x40207000, 0x1000, {},
61
+ /* Clear R[i] */
59
+ { .i2c_internal = true /* touchscreen */ } },
62
+ tcg_gen_mov_i32(cpu_R[i], zero);
60
+ { "i2c1", make_i2c, &mms->i2c[1], 0x40208000, 0x1000, {},
63
+ }
61
+ { .i2c_internal = true /* audio conf */ } },
64
+ }
62
+ { "i2c2", make_i2c, &mms->i2c[2], 0x4020c000, 0x1000, {},
65
+ if (extract32(a->list, 15, 1)) {
63
+ { .i2c_internal = false /* shield 0 */ } },
66
+ /*
64
+ { "i2c3", make_i2c, &mms->i2c[3], 0x4020d000, 0x1000, {},
67
+ * Clear APSR (by calling the MSR helper with the same argument
65
+ { .i2c_internal = false /* shield 1 */ } },
68
+ * as for "MSR APSR_nzcvqg, Rn": mask = 0b1100, SYSM=0)
66
},
69
+ */
67
}, {
70
+ TCGv_i32 maskreg = tcg_const_i32(0xc << 8);
68
.name = "apb_ppcexp2",
71
+ gen_helper_v7m_msr(cpu_env, maskreg, zero);
69
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
72
+ tcg_temp_free_i32(maskreg);
70
}, {
73
+ }
71
.name = "apb_ppcexp1",
74
+ tcg_temp_free_i32(zero);
72
.ports = {
75
+ return true;
73
- { "i2c0", make_i2c, &mms->i2c[0], 0x41200000, 0x1000 },
76
+}
74
- { "i2c1", make_i2c, &mms->i2c[1], 0x41201000, 0x1000 },
77
+
75
+ { "i2c0", make_i2c, &mms->i2c[0], 0x41200000, 0x1000, {},
78
/*
76
+ { .i2c_internal = true /* touchscreen */ } },
79
* Branch, branch with link
77
+ { "i2c1", make_i2c, &mms->i2c[1], 0x41201000, 0x1000, {},
80
*/
78
+ { .i2c_internal = true /* audio conf */ } },
79
{ "spi0", make_spi, &mms->spi[0], 0x41202000, 0x1000, { 52 } },
80
{ "spi1", make_spi, &mms->spi[1], 0x41203000, 0x1000, { 53 } },
81
{ "spi2", make_spi, &mms->spi[2], 0x41204000, 0x1000, { 54 } },
82
- { "i2c2", make_i2c, &mms->i2c[2], 0x41205000, 0x1000 },
83
- { "i2c3", make_i2c, &mms->i2c[3], 0x41206000, 0x1000 },
84
+ { "i2c2", make_i2c, &mms->i2c[2], 0x41205000, 0x1000, {},
85
+ { .i2c_internal = false /* shield 0 */ } },
86
+ { "i2c3", make_i2c, &mms->i2c[3], 0x41206000, 0x1000, {},
87
+ { .i2c_internal = false /* shield 1 */ } },
88
{ /* port 7 reserved */ },
89
- { "i2c4", make_i2c, &mms->i2c[4], 0x41208000, 0x1000 },
90
+ { "i2c4", make_i2c, &mms->i2c[4], 0x41208000, 0x1000, {},
91
+ { .i2c_internal = true /* DDR4 EEPROM */ } },
92
},
93
}, {
94
.name = "apb_ppcexp2",
95
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
96
}, {
97
.name = "apb_ppcexp1",
98
.ports = {
99
- { "i2c0", make_i2c, &mms->i2c[0], 0x49200000, 0x1000 },
100
- { "i2c1", make_i2c, &mms->i2c[1], 0x49201000, 0x1000 },
101
+ { "i2c0", make_i2c, &mms->i2c[0], 0x49200000, 0x1000, {},
102
+ { .i2c_internal = true /* touchscreen */ } },
103
+ { "i2c1", make_i2c, &mms->i2c[1], 0x49201000, 0x1000, {},
104
+ { .i2c_internal = true /* audio conf */ } },
105
{ "spi0", make_spi, &mms->spi[0], 0x49202000, 0x1000, { 53 } },
106
{ "spi1", make_spi, &mms->spi[1], 0x49203000, 0x1000, { 54 } },
107
{ "spi2", make_spi, &mms->spi[2], 0x49204000, 0x1000, { 55 } },
108
- { "i2c2", make_i2c, &mms->i2c[2], 0x49205000, 0x1000 },
109
- { "i2c3", make_i2c, &mms->i2c[3], 0x49206000, 0x1000 },
110
+ { "i2c2", make_i2c, &mms->i2c[2], 0x49205000, 0x1000, {},
111
+ { .i2c_internal = false /* shield 0 */ } },
112
+ { "i2c3", make_i2c, &mms->i2c[3], 0x49206000, 0x1000, {},
113
+ { .i2c_internal = false /* shield 1 */ } },
114
{ /* port 7 reserved */ },
115
- { "i2c4", make_i2c, &mms->i2c[4], 0x49208000, 0x1000 },
116
+ { "i2c4", make_i2c, &mms->i2c[4], 0x49208000, 0x1000, {},
117
+ { .i2c_internal = true /* DDR4 EEPROM */ } },
118
},
119
}, {
120
.name = "apb_ppcexp2",
81
--
121
--
82
2.20.1
122
2.20.1
83
123
84
124
diff view generated by jsdifflib
Deleted patch
1
For M-profile before v8.1M, the only valid register for VMSR/VMRS is
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
1
6
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
---
10
target/arm/translate-vfp.c.inc | 5 ++++-
11
1 file changed, 4 insertions(+), 1 deletion(-)
12
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
16
+++ b/target/arm/translate-vfp.c.inc
17
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
18
* Accesses to R15 are UNPREDICTABLE; we choose to undef.
19
* (FPSCR -> r15 is a special case which writes to the PSR flags.)
20
*/
21
- if (a->rt == 15 && (!a->l || a->reg != ARM_VFP_FPSCR)) {
22
+ if (a->reg != ARM_VFP_FPSCR) {
23
+ return false;
24
+ }
25
+ if (a->rt == 15 && !a->l) {
26
return false;
27
}
28
}
29
--
30
2.20.1
31
32
diff view generated by jsdifflib
Deleted patch
1
v8.1M defines a new FP system register FPSCR_nzcvqc; this behaves
2
like the existing FPSCR, except that it reads and writes only bits
3
[31:27] of the FPSCR (the N, Z, C, V and QC flag bits). (Unlike the
4
FPSCR, the special case for Rt=15 of writing the CPSR.NZCV is not
5
permitted.)
6
1
7
Implement the register. Since we don't yet implement MVE, we handle
8
the QC bit as RES0, with todo comments for where we will need to add
9
support later.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20201119215617.29887-11-peter.maydell@linaro.org
14
---
15
target/arm/cpu.h | 13 +++++++++++++
16
target/arm/translate-vfp.c.inc | 27 +++++++++++++++++++++++++++
17
2 files changed, 40 insertions(+)
18
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
22
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
26
#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
27
+#define FPCR_V (1 << 28) /* FP overflow flag */
28
+#define FPCR_C (1 << 29) /* FP carry flag */
29
+#define FPCR_Z (1 << 30) /* FP zero flag */
30
+#define FPCR_N (1 << 31) /* FP negative flag */
31
+
32
+#define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
33
+#define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
34
35
static inline uint32_t vfp_get_fpsr(CPUARMState *env)
36
{
37
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
38
#define ARM_VFP_FPEXC 8
39
#define ARM_VFP_FPINST 9
40
#define ARM_VFP_FPINST2 10
41
+/* These ones are M-profile only */
42
+#define ARM_VFP_FPSCR_NZCVQC 2
43
+#define ARM_VFP_VPR 12
44
+#define ARM_VFP_P0 13
45
+#define ARM_VFP_FPCXT_NS 14
46
+#define ARM_VFP_FPCXT_S 15
47
48
/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
49
#define QEMU_VFP_FPSCR_NZCV 0xffff
50
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate-vfp.c.inc
53
+++ b/target/arm/translate-vfp.c.inc
54
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
55
case ARM_VFP_FPSCR:
56
case QEMU_VFP_FPSCR_NZCV:
57
break;
58
+ case ARM_VFP_FPSCR_NZCVQC:
59
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
60
+ return false;
61
+ }
62
+ break;
63
default:
64
return FPSysRegCheckFailed;
65
}
66
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
67
tcg_temp_free_i32(tmp);
68
gen_lookup_tb(s);
69
break;
70
+ case ARM_VFP_FPSCR_NZCVQC:
71
+ {
72
+ TCGv_i32 fpscr;
73
+ tmp = loadfn(s, opaque);
74
+ /*
75
+ * TODO: when we implement MVE, write the QC bit.
76
+ * For non-MVE, QC is RES0.
77
+ */
78
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
79
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
80
+ tcg_gen_andi_i32(fpscr, fpscr, ~FPCR_NZCV_MASK);
81
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
82
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
83
+ tcg_temp_free_i32(tmp);
84
+ break;
85
+ }
86
default:
87
g_assert_not_reached();
88
}
89
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
90
gen_helper_vfp_get_fpscr(tmp, cpu_env);
91
storefn(s, opaque, tmp);
92
break;
93
+ case ARM_VFP_FPSCR_NZCVQC:
94
+ /*
95
+ * TODO: MVE has a QC bit, which we probably won't store
96
+ * in the xregs[] field. For non-MVE, where QC is RES0,
97
+ * we can just fall through to the FPSCR_NZCV case.
98
+ */
99
case QEMU_VFP_FPSCR_NZCV:
100
/*
101
* Read just NZCV; this is a special case to avoid the
102
--
103
2.20.1
104
105
diff view generated by jsdifflib
Deleted patch
1
We defined a constant name for the mask of NZCV bits in the FPCR/FPSCR
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
1
6
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
target/arm/translate-vfp.c.inc | 4 ++--
11
1 file changed, 2 insertions(+), 2 deletions(-)
12
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
16
+++ b/target/arm/translate-vfp.c.inc
17
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
18
* helper call for the "VMRS to CPSR.NZCV" insn.
19
*/
20
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
21
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
22
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
23
storefn(s, opaque, tmp);
24
break;
25
default:
26
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
27
case ARM_VFP_FPSCR:
28
if (a->rt == 15) {
29
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
30
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
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
--
36
2.20.1
37
38
diff view generated by jsdifflib
Deleted patch
1
The FPDSCR register has a similar layout to the FPSCR. In v8.1M it
2
gains new fields FZ16 (if half-precision floating point is supported)
3
and LTPSIZE (always reads as 4). Update the reset value and the code
4
that handles writes to this register accordingly.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-16-peter.maydell@linaro.org
9
---
10
target/arm/cpu.h | 5 +++++
11
hw/intc/armv7m_nvic.c | 9 ++++++++-
12
target/arm/cpu.c | 3 +++
13
3 files changed, 16 insertions(+), 1 deletion(-)
14
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
20
#define FPCR_IXE (1 << 12) /* Inexact exception trap enable */
21
#define FPCR_IDE (1 << 15) /* Input Denormal exception trap enable */
22
#define FPCR_FZ16 (1 << 19) /* ARMv8.2+, FP16 flush-to-zero */
23
+#define FPCR_RMODE_MASK (3 << 22) /* Rounding mode */
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
26
+#define FPCR_AHP (1 << 26) /* Alternative half-precision */
27
#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
28
#define FPCR_V (1 << 28) /* FP overflow flag */
29
#define FPCR_C (1 << 29) /* FP carry flag */
30
#define FPCR_Z (1 << 30) /* FP zero flag */
31
#define FPCR_N (1 << 31) /* FP negative flag */
32
33
+#define FPCR_LTPSIZE_SHIFT 16 /* LTPSIZE, M-profile only */
34
+#define FPCR_LTPSIZE_MASK (7 << FPCR_LTPSIZE_SHIFT)
35
+
36
#define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
37
#define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
38
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/intc/armv7m_nvic.c
42
+++ b/hw/intc/armv7m_nvic.c
43
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
44
break;
45
case 0xf3c: /* FPDSCR */
46
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
47
- value &= 0x07c00000;
48
+ uint32_t mask = FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK;
49
+ if (cpu_isar_feature(any_fp16, cpu)) {
50
+ mask |= FPCR_FZ16;
51
+ }
52
+ value &= mask;
53
+ if (cpu_isar_feature(aa32_lob, cpu)) {
54
+ value |= 4 << FPCR_LTPSIZE_SHIFT;
55
+ }
56
cpu->env.v7m.fpdscr[attrs.secure] = value;
57
}
58
break;
59
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/cpu.c
62
+++ b/target/arm/cpu.c
63
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
64
* always reset to 4.
65
*/
66
env->v7m.ltpsize = 4;
67
+ /* The LTPSIZE field in FPDSCR is constant and reads as 4. */
68
+ env->v7m.fpdscr[M_REG_NS] = 4 << FPCR_LTPSIZE_SHIFT;
69
+ env->v7m.fpdscr[M_REG_S] = 4 << FPCR_LTPSIZE_SHIFT;
70
}
71
72
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
73
--
74
2.20.1
75
76
diff view generated by jsdifflib
Deleted patch
1
In v8.0M, on exception entry the registers R0-R3, R12, APSR and EPSR
2
are zeroed for an exception taken to Non-secure state; for an
3
exception taken to Secure state they become UNKNOWN, and we chose to
4
leave them at their previous values.
5
1
6
In v8.1M the behaviour is specified more tightly and these registers
7
are always zeroed regardless of the security state that the exception
8
targets (see rule R_KPZV). Implement this.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20201119215617.29887-17-peter.maydell@linaro.org
13
---
14
target/arm/m_helper.c | 16 ++++++++++++----
15
1 file changed, 12 insertions(+), 4 deletions(-)
16
17
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/m_helper.c
20
+++ b/target/arm/m_helper.c
21
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
22
* Clear registers if necessary to prevent non-secure exception
23
* code being able to see register values from secure code.
24
* Where register values become architecturally UNKNOWN we leave
25
- * them with their previous values.
26
+ * them with their previous values. v8.1M is tighter than v8.0M
27
+ * here and always zeroes the caller-saved registers regardless
28
+ * of the security state the exception is targeting.
29
*/
30
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
31
- if (!targets_secure) {
32
+ if (!targets_secure || arm_feature(env, ARM_FEATURE_V8_1M)) {
33
/*
34
* Always clear the caller-saved registers (they have been
35
* pushed to the stack earlier in v7m_push_stack()).
36
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
37
* v7m_push_callee_stack()).
38
*/
39
int i;
40
+ /*
41
+ * r4..r11 are callee-saves, zero only if background
42
+ * state was Secure (EXCRET.S == 1) and exception
43
+ * targets Non-secure state
44
+ */
45
+ bool zero_callee_saves = !targets_secure &&
46
+ (lr & R_V7M_EXCRET_S_MASK);
47
48
for (i = 0; i < 13; i++) {
49
- /* r4..r11 are callee-saves, zero only if EXCRET.S == 1 */
50
- if (i < 4 || i > 11 || (lr & R_V7M_EXCRET_S_MASK)) {
51
+ if (i < 4 || i > 11 || zero_callee_saves) {
52
env->regs[i] = 0;
53
}
54
}
55
--
56
2.20.1
57
58
diff view generated by jsdifflib
Deleted patch
1
In v8.1M, vector table fetch failures don't set HFSR.FORCED (see rule
2
R_LLRP). (In previous versions of the architecture this was either
3
required or IMPDEF.)
4
1
5
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
---
9
target/arm/m_helper.c | 6 +++++-
10
1 file changed, 5 insertions(+), 1 deletion(-)
11
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/m_helper.c
15
+++ b/target/arm/m_helper.c
16
@@ -XXX,XX +XXX,XX @@ load_fail:
17
* The HardFault is Secure if BFHFNMINS is 0 (meaning that all HFs are
18
* secure); otherwise it targets the same security state as the
19
* underlying exception.
20
+ * In v8.1M HardFaults from vector table fetch fails don't set FORCED.
21
*/
22
if (!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
23
exc_secure = true;
24
}
25
- env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK | R_V7M_HFSR_FORCED_MASK;
26
+ env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK;
27
+ if (!arm_feature(env, ARM_FEATURE_V8_1M)) {
28
+ env->v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
29
+ }
30
armv7m_nvic_set_pending_derived(env->nvic, ARMV7M_EXCP_HARD, exc_secure);
31
return false;
32
}
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
Deleted patch
1
In v8.1M a REVIDR register is defined, which is at address 0xe00ecfc
2
and is a read-only IMPDEF register providing implementation specific
3
minor revision information, like the v8A REVIDR_EL1. Implement this.
4
1
5
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
---
9
hw/intc/armv7m_nvic.c | 5 +++++
10
1 file changed, 5 insertions(+)
11
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/armv7m_nvic.c
15
+++ b/hw/intc/armv7m_nvic.c
16
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
17
}
18
return val;
19
}
20
+ case 0xcfc:
21
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8_1M)) {
22
+ goto bad_offset;
23
+ }
24
+ return cpu->revidr;
25
case 0xd00: /* CPUID Base. */
26
return cpu->midr;
27
case 0xd04: /* Interrupt Control State (ICSR) */
28
--
29
2.20.1
30
31
diff view generated by jsdifflib
Deleted patch
1
In v8.1M a new exception return check is added which may cause a NOCP
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
1
6
(Note that for our implementation CPPWR is always RAZ/WI and so can
7
never cause CP10 accesses to fail.)
8
9
The other v8.1M change to this register-clearing code is that if MVE
10
is implemented VPR must also be cleared, so add a TODO comment to
11
that effect.
12
13
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
---
17
target/arm/m_helper.c | 22 +++++++++++++++++++++-
18
1 file changed, 21 insertions(+), 1 deletion(-)
19
20
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/m_helper.c
23
+++ b/target/arm/m_helper.c
24
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
25
v7m_exception_taken(cpu, excret, true, false);
26
return;
27
} else {
28
- /* Clear s0..s15 and FPSCR */
29
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
30
+ /* v8.1M adds this NOCP check */
31
+ bool nsacr_pass = exc_secure ||
32
+ extract32(env->v7m.nsacr, 10, 1);
33
+ bool cpacr_pass = v7m_cpacr_pass(env, exc_secure, true);
34
+ if (!nsacr_pass) {
35
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, true);
36
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_NOCP_MASK;
37
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
38
+ "stackframe: NSACR prevents clearing FPU registers\n");
39
+ v7m_exception_taken(cpu, excret, true, false);
40
+ } else if (!cpacr_pass) {
41
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
42
+ exc_secure);
43
+ env->v7m.cfsr[exc_secure] |= R_V7M_CFSR_NOCP_MASK;
44
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
45
+ "stackframe: CPACR prevents clearing FPU registers\n");
46
+ v7m_exception_taken(cpu, excret, true, false);
47
+ }
48
+ }
49
+ /* Clear s0..s15 and FPSCR; TODO also VPR when MVE is implemented */
50
int i;
51
52
for (i = 0; i < 16; i += 2) {
53
--
54
2.20.1
55
56
diff view generated by jsdifflib
Deleted patch
1
v8.1M introduces a new TRD flag in the CCR register, which enables
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
1
6
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
---
10
target/arm/cpu.h | 2 ++
11
hw/intc/armv7m_nvic.c | 26 ++++++++++++++++++--------
12
2 files changed, 20 insertions(+), 8 deletions(-)
13
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_CCR, STKOFHFNMIGN, 10, 1)
19
FIELD(V7M_CCR, DC, 16, 1)
20
FIELD(V7M_CCR, IC, 17, 1)
21
FIELD(V7M_CCR, BP, 18, 1)
22
+FIELD(V7M_CCR, LOB, 19, 1)
23
+FIELD(V7M_CCR, TRD, 20, 1)
24
25
/* V7M SCR bits */
26
FIELD(V7M_SCR, SLEEPONEXIT, 1, 1)
27
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/intc/armv7m_nvic.c
30
+++ b/hw/intc/armv7m_nvic.c
31
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
32
}
33
return cpu->env.v7m.scr[attrs.secure];
34
case 0xd14: /* Configuration Control. */
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
}
53
54
/* Enforce RAZ/WI on reserved and must-RAZ/WI bits */
55
- value &= (R_V7M_CCR_STKALIGN_MASK |
56
- R_V7M_CCR_BFHFNMIGN_MASK |
57
- R_V7M_CCR_DIV_0_TRP_MASK |
58
- R_V7M_CCR_UNALIGN_TRP_MASK |
59
- R_V7M_CCR_USERSETMPEND_MASK |
60
- R_V7M_CCR_NONBASETHRDENA_MASK);
61
+ mask = R_V7M_CCR_STKALIGN_MASK |
62
+ R_V7M_CCR_BFHFNMIGN_MASK |
63
+ R_V7M_CCR_DIV_0_TRP_MASK |
64
+ R_V7M_CCR_UNALIGN_TRP_MASK |
65
+ R_V7M_CCR_USERSETMPEND_MASK |
66
+ R_V7M_CCR_NONBASETHRDENA_MASK;
67
+ if (arm_feature(&cpu->env, ARM_FEATURE_V8_1M) && attrs.secure) {
68
+ /* TRD is always RAZ/WI from NS */
69
+ mask |= R_V7M_CCR_TRD_MASK;
70
+ }
71
+ value &= mask;
72
73
if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
74
/* v8M makes NONBASETHRDENA and STKALIGN be RES1 */
75
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
76
77
cpu->env.v7m.ccr[attrs.secure] = value;
78
break;
79
+ }
80
case 0xd24: /* System Handler Control and State (SHCSR) */
81
if (!arm_feature(&cpu->env, ARM_FEATURE_V7)) {
82
goto bad_offset;
83
--
84
2.20.1
85
86
diff view generated by jsdifflib
1
Correct a typo in the name we give the NVIC object.
1
The various MPS2 boards implemented in mps2.c have multiple I2C
2
buses: a bus dedicated to the audio configuration, one for the LCD
3
touchscreen controller, and two which are connected to the external
4
Shield expansion connector. Mark the buses which are used only for
5
board-internal devices as 'full' so that if the user creates i2c
6
devices on the commandline without specifying a bus name then they
7
will be connected to the I2C controller used for the Shield
8
connector, where guest software will expect them.
2
9
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201119215617.29887-28-peter.maydell@linaro.org
12
Message-id: 20210903151435.22379-5-peter.maydell@linaro.org
7
---
13
---
8
hw/arm/armv7m.c | 2 +-
14
hw/arm/mps2.c | 12 +++++++++++-
9
1 file changed, 1 insertion(+), 1 deletion(-)
15
1 file changed, 11 insertions(+), 1 deletion(-)
10
16
11
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
17
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/armv7m.c
19
--- a/hw/arm/mps2.c
14
+++ b/hw/arm/armv7m.c
20
+++ b/hw/arm/mps2.c
15
@@ -XXX,XX +XXX,XX @@ static void armv7m_instance_init(Object *obj)
21
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
16
22
0x40023000, /* Audio */
17
memory_region_init(&s->container, obj, "armv7m-container", UINT64_MAX);
23
0x40029000, /* Shield0 */
18
24
0x4002a000}; /* Shield1 */
19
- object_initialize_child(obj, "nvnic", &s->nvic, TYPE_NVIC);
25
- sysbus_create_simple(TYPE_ARM_SBCON_I2C, i2cbase[i], NULL);
20
+ object_initialize_child(obj, "nvic", &s->nvic, TYPE_NVIC);
26
+ DeviceState *dev;
21
object_property_add_alias(obj, "num-irq",
27
+
22
OBJECT(&s->nvic), "num-irq");
28
+ dev = sysbus_create_simple(TYPE_ARM_SBCON_I2C, i2cbase[i], NULL);
29
+ if (i < 2) {
30
+ /*
31
+ * internal-only bus: mark it full to avoid user-created
32
+ * i2c devices being plugged into it.
33
+ */
34
+ BusState *qbus = qdev_get_child_bus(dev, "i2c");
35
+ qbus_mark_full(qbus);
36
+ }
37
}
38
create_unimplemented_device("i2s", 0x40024000, 0x400);
23
39
24
--
40
--
25
2.20.1
41
2.20.1
26
42
27
43
diff view generated by jsdifflib